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;
1663 SilcPacketContext *packet = silc_packet_context_alloc();
1665 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1666 buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1667 1, idp->data, idp->len);
1669 packet->buffer = silc_buffer_copy(buffer);
1670 packet->sock = sock;
1671 packet->type = SILC_PACKET_COMMAND;
1673 cmd = silc_calloc(1, sizeof(*cmd));
1674 cmd->payload = silc_command_payload_parse(buffer);
1675 cmd->args = silc_command_get_args(cmd->payload);
1676 cmd->server = server;
1678 cmd->packet = silc_packet_context_dup(packet);
1679 cmd->pending = FALSE;
1681 silc_server_command_names((void *)cmd);
1685 silc_packet_context_free(packet);
1688 /* Internal routine that is called after router has replied to server's
1689 JOIN command it forwarded to the router. The route has joined and possibly
1690 creaetd the channel. This function adds the client to the channel's user
1693 SILC_SERVER_CMD_FUNC(add_to_channel)
1695 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1696 SilcServer server = cmd->server;
1697 SilcClientEntry client;
1698 SilcChannelEntry channel;
1699 SilcChannelClientEntry chl;
1702 /* Get channel name */
1703 channel_name = silc_argument_get_arg_type(cmd->args, 1, NULL);
1705 /* Get client entry */
1706 client = (SilcClientEntry)cmd->sock->user_data;
1708 /* Get channel entry */
1709 channel = silc_idlist_find_channel_by_name(server->local_list,
1710 channel_name, NULL);
1712 /* Join the client to the channel by adding it to channel's user list.
1713 Add also the channel to client entry's channels list for fast cross-
1715 chl = silc_calloc(1, sizeof(*chl));
1716 //chl->mode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
1717 chl->client = client;
1718 chl->channel = channel;
1719 silc_list_add(channel->user_list, chl);
1720 silc_list_add(client->channels, chl);
1723 silc_server_command_free(cmd);
1726 /* Internal routine to join channel. The channel sent to this function
1727 has been either created or resolved from ID lists. This joins the sent
1728 client to the channel. */
1730 static void silc_server_command_join_channel(SilcServer server,
1731 SilcServerCommandContext cmd,
1732 SilcChannelEntry channel,
1733 SilcClientID *client_id,
1737 SilcSocketConnection sock = cmd->sock;
1739 unsigned int tmp_len;
1740 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1741 SilcClientEntry client;
1742 SilcChannelClientEntry chl;
1743 SilcBuffer reply, chidp, clidp, keyp;
1744 unsigned short ident = silc_command_get_ident(cmd->payload);
1746 SILC_LOG_DEBUG(("Start"));
1751 /* Get passphrase */
1752 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1754 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1755 memcpy(passphrase, tmp, tmp_len);
1759 * Check channel modes
1762 /* Check invite list if channel is invite-only channel */
1763 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1764 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1765 /* Invite list is specified. Check whether client is invited in the
1766 list. If not, then check whether it has been invited otherwise. */
1769 /* XXX client must be invited to be able to join the channel */
1773 /* Check ban list if set */
1774 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1778 /* Check the channel passphrase if set. */
1779 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1780 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1781 strlen(channel->mode_data.passphrase))) {
1782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1783 SILC_STATUS_ERR_BAD_PASSWORD);
1788 /* Check user count limit if set. */
1789 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1790 if (silc_list_count(channel->user_list) + 1 >
1791 channel->mode_data.user_limit) {
1792 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1793 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1799 * Client is allowed to join to the channel. Make it happen.
1802 /* Get the client entry */
1803 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1804 client = (SilcClientEntry)sock->user_data;
1806 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1809 /* XXX actually this is useless since router finds always cell's
1810 local clients from its local lists. */
1811 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1818 /* Check whether the client already is on the channel */
1819 if (silc_server_client_on_channel(client, channel)) {
1820 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1821 SILC_STATUS_ERR_USER_ON_CHANNEL);
1825 /* Generate new channel key as protocol dictates */
1826 if (!created || !channel->channel_key)
1827 silc_server_create_channel_key(server, channel, 0);
1829 /* Send the channel key. This is broadcasted to the channel but is not
1830 sent to the client who is joining to the channel. */
1831 silc_server_send_channel_key(server, channel,
1832 server->server_type == SILC_ROUTER ?
1833 FALSE : server->standalone);
1835 /* Join the client to the channel by adding it to channel's user list.
1836 Add also the channel to client entry's channels list for fast cross-
1838 chl = silc_calloc(1, sizeof(*chl));
1840 chl->client = client;
1841 chl->channel = channel;
1842 silc_list_add(channel->user_list, chl);
1843 silc_list_add(client->channels, chl);
1845 /* Encode Client ID Payload of the original client who wants to join */
1846 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1848 /* Encode command reply packet */
1849 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1850 SILC_PUT32_MSB(channel->mode, mode);
1851 SILC_PUT32_MSB(created, tmp2);
1852 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1853 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1854 SILC_ID_CHANNEL_LEN,
1855 channel->channel_key->cipher->name,
1856 channel->key_len / 8, channel->key);
1858 if (!channel->topic) {
1860 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1861 SILC_STATUS_OK, ident, 5,
1862 2, channel->channel_name,
1863 strlen(channel->channel_name),
1864 3, chidp->data, chidp->len,
1867 6, keyp->data, keyp->len);
1870 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1871 SILC_STATUS_OK, ident, 6,
1872 2, channel->channel_name,
1873 strlen(channel->channel_name),
1874 3, chidp->data, chidp->len,
1877 6, keyp->data, keyp->len,
1879 strlen(channel->topic));
1882 /* Send command reply */
1883 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1884 reply->data, reply->len, FALSE);
1887 /* Send JOIN notify to locally connected clients on the channel */
1888 silc_server_send_notify_to_channel(server, channel, FALSE,
1889 SILC_NOTIFY_TYPE_JOIN, 1,
1890 clidp->data, clidp->len);
1892 /* Send NEW_CHANNEL_USER packet to our primary router */
1893 if (!cmd->pending && !server->standalone)
1894 silc_server_send_new_channel_user(server, server->router->connection,
1895 server->server_type == SILC_SERVER ?
1897 channel->id, SILC_ID_CHANNEL_LEN,
1898 client->id, SILC_ID_CLIENT_LEN);
1900 /* Send NAMES command reply to the joined channel so the user sees who
1901 is currently on the channel. */
1902 silc_server_command_send_names(server, sock, channel);
1908 * Kuinka NAMES komento händlätään serverissä kun router lähettää sen
1909 serverille joka on lähettäny sille clientin puolesta JOIN komennon?
1911 R: Serverin pitää ymmärtää NAMES comman replyjä.
1915 silc_buffer_free(reply);
1916 silc_buffer_free(clidp);
1917 silc_buffer_free(chidp);
1918 silc_buffer_free(keyp);
1922 silc_free(passphrase);
1925 /* Server side of command JOIN. Joins client into requested channel. If
1926 the channel does not exist it will be created. */
1928 SILC_SERVER_CMD_FUNC(join)
1930 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1931 SilcServer server = cmd->server;
1933 char *tmp, *channel_name = NULL, *cipher = NULL;
1934 SilcChannelEntry channel;
1935 unsigned int umode = 0;
1936 int created = FALSE;
1937 SilcClientID *client_id;
1939 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1941 /* Get channel name */
1942 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1945 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1950 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1951 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1952 SILC_STATUS_ERR_BAD_CHANNEL);
1953 silc_free(channel_name);
1957 /* Get Client ID of the client who is joining to the channel */
1958 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1960 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1961 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1964 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1966 /* Get cipher name */
1967 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
1969 /* See if the channel exists */
1970 channel = silc_idlist_find_channel_by_name(server->local_list,
1971 channel_name, NULL);
1973 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1974 /* If this is coming from client the Client ID in the command packet must
1975 be same as the client's ID. */
1976 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1977 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
1978 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
1979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1980 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1986 /* Channel not found */
1988 /* If we are standalone server we don't have a router, we just create
1989 the channel by ourselves. */
1990 if (server->standalone) {
1991 channel = silc_server_create_new_channel(server, server->id, cipher,
1993 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1998 /* The channel does not exist on our server. If we are normal server
1999 we will send JOIN command to our router which will handle the
2000 joining procedure (either creates the channel if it doesn't exist
2001 or joins the client to it). */
2002 if (server->server_type == SILC_SERVER) {
2004 unsigned short old_ident;
2006 old_ident = silc_command_get_ident(cmd->payload);
2007 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2008 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2010 /* Send JOIN command to our router */
2011 silc_server_packet_send(server, (SilcSocketConnection)
2012 server->router->connection,
2013 SILC_PACKET_COMMAND, cmd->packet->flags,
2014 tmpbuf->data, tmpbuf->len, TRUE);
2016 /* Reprocess this packet after received reply from router */
2017 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2018 silc_command_get_ident(cmd->payload),
2019 silc_server_command_join, context);
2020 cmd->pending = TRUE;
2024 /* We are router and the channel does not seem exist so we will check
2025 our global list as well for the channel. */
2026 channel = silc_idlist_find_channel_by_name(server->global_list,
2027 channel_name, NULL);
2029 /* Channel really does not exist, create it */
2030 channel = silc_server_create_new_channel(server, server->id, cipher,
2032 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2039 /* Channel not found */
2041 /* If the command came from router and/or we are normal server then
2042 something went wrong with the joining as the channel was not found.
2043 We can't do anything else but ignore this. */
2044 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2045 server->server_type == SILC_SERVER)
2048 /* We are router and the channel does not seem exist so we will check
2049 our global list as well for the channel. */
2050 channel = silc_idlist_find_channel_by_name(server->global_list,
2051 channel_name, NULL);
2053 /* Channel really does not exist, create it */
2054 channel = silc_server_create_new_channel(server, server->id, cipher,
2056 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2062 /* If the channel does not have global users and is also empty it means the
2063 channel was created globally (by our router) and the client will be the
2064 channel founder and operator. */
2065 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2066 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2067 created = TRUE; /* Created globally by our router */
2070 /* Join to the channel */
2071 silc_server_command_join_channel(server, cmd, channel, client_id,
2074 silc_free(client_id);
2077 silc_server_command_free(cmd);
2080 /* Server side of command MOTD. Sends server's current "message of the
2081 day" to the client. */
2083 SILC_SERVER_CMD_FUNC(motd)
2085 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2086 SilcServer server = cmd->server;
2090 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2092 /* XXX show currently only our motd */
2094 if (server->config && server->config->motd &&
2095 server->config->motd->motd_file) {
2098 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2103 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2114 silc_server_command_free(cmd);
2117 SILC_SERVER_CMD_FUNC(umode)
2121 /* Checks that client has rights to add or remove channel modes. If any
2122 of the checks fails FALSE is returned. */
2124 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2125 SilcChannelClientEntry client,
2128 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2129 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2131 /* Check whether has rights to change anything */
2132 if (!is_op && !is_fo)
2135 /* Check whether has rights to change everything */
2139 /* We know that client is channel operator, check that they are not
2140 changing anything that requires channel founder rights. Rest of the
2141 modes are available automatically for channel operator. */
2143 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2144 if (is_op && !is_fo)
2147 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2148 if (is_op && !is_fo)
2153 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2154 if (is_op && !is_fo)
2157 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2158 if (is_op && !is_fo)
2163 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2164 if (is_op && !is_fo)
2167 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2168 if (is_op && !is_fo)
2176 /* Server side command of CMODE. Changes channel mode */
2178 SILC_SERVER_CMD_FUNC(cmode)
2180 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2181 SilcServer server = cmd->server;
2182 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2183 SilcChannelID *channel_id;
2184 SilcChannelEntry channel;
2185 SilcChannelClientEntry chl;
2186 SilcBuffer packet, cidp;
2187 unsigned char *tmp, *tmp_id, *tmp_mask;
2188 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2190 SILC_LOG_DEBUG(("Start"));
2192 argc = silc_argument_get_arg_num(cmd->args);
2194 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2195 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2199 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2200 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2204 /* Get Channel ID */
2205 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2207 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2208 SILC_STATUS_ERR_NO_CHANNEL_ID);
2211 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2213 /* Get the channel mode mask */
2214 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2216 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2217 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2220 SILC_GET32_MSB(mode_mask, tmp_mask);
2222 /* Get channel entry */
2223 channel = silc_idlist_find_channel_by_id(server->local_list,
2226 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2227 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2231 /* Check whether this client is on the channel */
2232 if (!silc_server_client_on_channel(client, channel)) {
2233 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2234 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2238 /* Get entry to the channel user list */
2239 silc_list_start(channel->user_list);
2240 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2241 if (chl->client == client)
2244 /* Check that client has rights to change any requested channel modes */
2245 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2246 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2247 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2252 * Check the modes. Modes that requires nothing special operation are
2256 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2257 /* Channel uses private keys to protect traffic. Client(s) has set the
2258 key locally they want to use, server does not know that key. */
2259 /* Nothing interesting to do here now */
2261 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2262 /* The mode is removed and we need to generate and distribute
2263 new channel key. Clients are not using private channel keys
2264 anymore after this. */
2266 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2269 /* Re-generate channel key */
2270 silc_server_create_channel_key(server, channel, 0);
2272 /* Encode channel key payload to be distributed on the channel */
2274 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2275 strlen(channel->channel_key->
2277 channel->channel_key->cipher->name,
2278 channel->key_len / 8, channel->key);
2280 /* If we are normal server then we will send it to our router. If we
2281 are router we will send it to all local servers that has clients on
2283 if (server->server_type == SILC_SERVER) {
2284 if (!server->standalone)
2285 silc_server_packet_send(server,
2286 cmd->server->router->connection,
2287 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2293 /* Send to locally connected clients on the channel */
2294 silc_server_packet_send_local_channel(server, channel,
2295 SILC_PACKET_CHANNEL_KEY, 0,
2296 packet->data, packet->len, FALSE);
2297 silc_buffer_free(packet);
2301 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2302 /* User limit is set on channel */
2303 unsigned int user_limit;
2305 /* Get user limit */
2306 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2308 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2310 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2314 SILC_GET32_MSB(user_limit, tmp);
2315 channel->mode_data.user_limit = user_limit;
2318 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2319 /* User limit mode is unset. Remove user limit */
2320 channel->mode_data.user_limit = 0;
2323 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2324 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2325 /* Passphrase has been set to channel */
2327 /* Get the passphrase */
2328 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2331 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2335 /* Save the passphrase */
2336 channel->mode_data.passphrase = strdup(tmp);
2339 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2340 /* Passphrase mode is unset. remove the passphrase */
2341 if (channel->mode_data.passphrase) {
2342 silc_free(channel->mode_data.passphrase);
2343 channel->mode_data.passphrase = NULL;
2348 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2349 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2350 /* Ban list is specified for channel */
2353 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2355 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2356 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2360 /* XXX check that channel founder is not banned */
2362 /* Save the ban list */
2363 channel->mode_data.ban_list = strdup(tmp);
2366 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2367 /* Ban mode is unset. Remove the entire ban list */
2368 if (channel->mode_data.ban_list) {
2369 silc_free(channel->mode_data.ban_list);
2370 channel->mode_data.ban_list = NULL;
2375 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2376 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2377 /* Invite list is specified for channel */
2379 /* Get invite list */
2380 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2383 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2387 /* Save the invite linst */
2388 channel->mode_data.invite_list = strdup(tmp);
2391 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2392 /* Invite list mode is unset. Remove the entire invite list */
2393 if (channel->mode_data.invite_list) {
2394 silc_free(channel->mode_data.invite_list);
2395 channel->mode_data.invite_list = NULL;
2400 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2401 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2402 /* Cipher to use protect the traffic */
2403 unsigned int key_len = 128;
2407 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2410 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2414 cp = strchr(tmp, ':');
2420 /* XXX Duplicated code, make own function for this!! */
2422 /* Delete old cipher and allocate the new one */
2423 silc_cipher_free(channel->channel_key);
2424 silc_cipher_alloc(tmp, &channel->channel_key);
2430 /* Re-generate channel key */
2431 silc_server_create_channel_key(server, channel, key_len);
2433 /* Encode channel key payload to be distributed on the channel */
2435 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2436 strlen(channel->channel_key->
2438 channel->channel_key->cipher->name,
2439 channel->key_len / 8, channel->key);
2441 /* If we are normal server then we will send it to our router. If we
2442 are router we will send it to all local servers that has clients on
2444 if (server->server_type == SILC_SERVER) {
2445 if (!server->standalone)
2446 silc_server_packet_send(server,
2447 cmd->server->router->connection,
2448 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2454 /* Send to locally connected clients on the channel */
2455 silc_server_packet_send_local_channel(server, channel,
2456 SILC_PACKET_CHANNEL_KEY, 0,
2457 packet->data, packet->len, FALSE);
2458 silc_buffer_free(packet);
2461 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2462 /* Cipher mode is unset. Remove the cipher and revert back to
2465 if (channel->mode_data.cipher) {
2466 silc_free(channel->mode_data.cipher);
2467 channel->mode_data.cipher = NULL;
2468 channel->mode_data.key_len = 0;
2471 /* Generate new cipher and key for the channel */
2473 /* XXX Duplicated code, make own function for this!! */
2475 /* Delete old cipher and allocate default one */
2476 silc_cipher_free(channel->channel_key);
2477 if (!channel->cipher)
2478 silc_cipher_alloc("twofish", &channel->channel_key);
2480 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2482 /* Re-generate channel key */
2483 silc_server_create_channel_key(server, channel, 0);
2485 /* Encode channel key payload to be distributed on the channel */
2487 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2488 strlen(channel->channel_key->
2490 channel->channel_key->cipher->name,
2491 channel->key_len / 8, channel->key);
2493 /* If we are normal server then we will send it to our router. If we
2494 are router we will send it to all local servers that has clients on
2496 if (server->server_type == SILC_SERVER) {
2497 if (!server->standalone)
2498 silc_server_packet_send(server,
2499 cmd->server->router->connection,
2500 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2506 /* Send to locally connected clients on the channel */
2507 silc_server_packet_send_local_channel(server, channel,
2508 SILC_PACKET_CHANNEL_KEY, 0,
2509 packet->data, packet->len, FALSE);
2510 silc_buffer_free(packet);
2514 /* Finally, set the mode */
2515 channel->mode = mode_mask;
2517 /* Send CMODE_CHANGE notify */
2518 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2519 silc_server_send_notify_to_channel(server, channel, TRUE,
2520 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2521 cidp->data, cidp->len,
2525 /* Send command reply to sender */
2526 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2527 SILC_STATUS_OK, 0, 1,
2529 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2530 packet->data, packet->len, FALSE);
2532 silc_buffer_free(packet);
2533 silc_free(channel_id);
2536 silc_server_command_free(cmd);
2539 /* Server side of CUMODE command. Changes client's mode on a channel. */
2541 SILC_SERVER_CMD_FUNC(cumode)
2543 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2544 SilcServer server = cmd->server;
2545 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2546 SilcChannelID *channel_id;
2547 SilcClientID *client_id;
2548 SilcChannelEntry channel;
2549 SilcClientEntry target_client;
2550 SilcChannelClientEntry chl;
2551 SilcBuffer packet, idp;
2552 unsigned char *tmp_id, *tmp_mask;
2553 unsigned int target_mask, sender_mask, tmp_len;
2556 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2558 /* Get Channel ID */
2559 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2561 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2562 SILC_STATUS_ERR_NO_CHANNEL_ID);
2565 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2567 /* Get channel entry */
2568 channel = silc_idlist_find_channel_by_id(server->local_list,
2571 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2572 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2576 /* Check whether sender is on the channel */
2577 if (!silc_server_client_on_channel(client, channel)) {
2578 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2579 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2583 /* Check that client has rights to change other's rights */
2584 silc_list_start(channel->user_list);
2585 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2586 if (chl->client == client) {
2587 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2588 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2589 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2590 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2594 sender_mask = chl->mode;
2599 /* Get the target client's channel mode mask */
2600 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2603 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2606 SILC_GET32_MSB(target_mask, tmp_mask);
2608 /* Get target Client ID */
2609 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2612 SILC_STATUS_ERR_NO_CHANNEL_ID);
2615 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2617 /* Get target client's entry */
2618 target_client = silc_idlist_find_client_by_id(server->local_list,
2620 if (!target_client) {
2621 /* XXX If target client is not one of mine send to primary route */
2624 /* Check whether target client is on the channel */
2625 if (!silc_server_client_on_channel(target_client, channel)) {
2626 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2627 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2631 /* Get entry to the channel user list */
2632 silc_list_start(channel->user_list);
2633 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2634 if (chl->client == target_client)
2641 /* If the target client is founder, no one else can change their mode
2643 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2644 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2645 SILC_STATUS_ERR_NOT_YOU);
2649 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2650 /* Cannot promote anyone to channel founder */
2651 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2652 SILC_STATUS_ERR_NOT_YOU);
2655 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2656 if (target_client == client) {
2657 /* Remove channel founder rights from itself */
2658 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2661 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2662 SILC_STATUS_ERR_NOT_YOU);
2668 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2669 /* Promote to operator */
2670 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2671 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2675 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2676 /* Demote to normal user */
2677 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2682 /* Send notify to channel, notify only if mode was actually changed. */
2684 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2685 silc_server_send_notify_to_channel(server, channel, TRUE,
2686 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2687 idp->data, idp->len,
2688 tmp_mask, 4, tmp_id, tmp_len);
2689 silc_buffer_free(idp);
2692 /* Send command reply to sender */
2693 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2694 SILC_STATUS_OK, 0, 2,
2696 3, tmp_id, tmp_len);
2697 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2698 packet->data, packet->len, FALSE);
2700 silc_buffer_free(packet);
2701 silc_free(channel_id);
2702 silc_free(client_id);
2705 silc_server_command_free(cmd);
2708 /* Server side of KICK command. Kicks client out of channel. */
2710 SILC_SERVER_CMD_FUNC(kick)
2714 SILC_SERVER_CMD_FUNC(restart)
2718 SILC_SERVER_CMD_FUNC(close)
2722 SILC_SERVER_CMD_FUNC(die)
2726 SILC_SERVER_CMD_FUNC(silcoper)
2730 /* Server side command of LEAVE. Removes client from a channel. */
2732 SILC_SERVER_CMD_FUNC(leave)
2734 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2735 SilcServer server = cmd->server;
2736 SilcSocketConnection sock = cmd->sock;
2737 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2739 SilcChannelEntry channel;
2741 unsigned int i, len;
2744 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2746 /* Get Channel ID */
2747 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2749 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2750 SILC_STATUS_ERR_NO_CHANNEL_ID);
2753 id = silc_id_payload_parse_id(tmp, len);
2755 /* Get channel entry */
2756 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2758 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2759 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2763 /* Check whether this client is on the channel */
2764 if (!silc_server_client_on_channel(id_entry, channel)) {
2765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2766 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2770 /* Notify routers that they should remove this client from their list
2771 of clients on the channel. */
2772 if (!server->standalone)
2773 silc_server_send_remove_channel_user(server,
2774 server->router->connection,
2775 server->server_type == SILC_ROUTER ?
2776 TRUE : FALSE, id_entry->id, id);
2778 /* Remove client from channel */
2779 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2781 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2784 /* If the channel does not exist anymore we won't send anything */
2788 /* Re-generate channel key */
2789 silc_server_create_channel_key(server, channel, 0);
2791 /* Encode channel key payload to be distributed on the channel */
2793 silc_channel_key_payload_encode(len, tmp,
2794 strlen(channel->channel_key->cipher->name),
2795 channel->channel_key->cipher->name,
2796 channel->key_len / 8, channel->key);
2798 /* If we are normal server then we will send it to our router. If we
2799 are router we will send it to all local servers that has clients on
2801 if (server->server_type == SILC_SERVER) {
2802 if (!server->standalone)
2803 silc_server_packet_send(server,
2804 cmd->server->router->connection,
2805 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2811 /* Send to locally connected clients on the channel */
2812 silc_server_packet_send_local_channel(server, channel,
2813 SILC_PACKET_CHANNEL_KEY, 0,
2814 packet->data, packet->len, FALSE);
2816 silc_buffer_free(packet);
2820 silc_server_command_free(cmd);
2823 /* Server side of command NAMES. Resolves clients and their names currently
2824 joined on the requested channel. The name list is sent back to the
2827 SILC_SERVER_CMD_FUNC(names)
2829 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2830 SilcServer server = cmd->server;
2831 SilcChannelEntry channel;
2832 SilcChannelClientEntry chl;
2835 unsigned int i, len, len2, tmp_len;
2837 char *name_list = NULL, *n;
2838 SilcBuffer client_id_list;
2839 SilcBuffer client_mode_list;
2841 unsigned short ident = silc_command_get_ident(cmd->payload);
2843 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NAMES, cmd, 1, 2);
2845 /* Get Channel ID */
2846 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2849 SILC_STATUS_ERR_NO_CHANNEL_ID);
2852 id = silc_id_payload_parse_id(tmp, tmp_len);
2854 if (server->server_type == SILC_SERVER && !server->standalone &&
2858 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2859 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2861 /* Send NAMES command */
2862 silc_server_packet_send(server, server->router->connection,
2863 SILC_PACKET_COMMAND, cmd->packet->flags,
2864 tmpbuf->data, tmpbuf->len, TRUE);
2866 /* Reprocess this packet after received reply */
2867 silc_server_command_pending(server, SILC_COMMAND_NAMES,
2868 silc_command_get_ident(cmd->payload),
2869 silc_server_command_names, (void *)cmd);
2870 cmd->pending = TRUE;
2871 silc_command_set_ident(cmd->payload, ident);
2873 silc_buffer_free(tmpbuf);
2878 /* Get the channel entry */
2879 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2881 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2883 /* Channel really does not exist */
2884 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2885 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2890 /* Assemble the lists now */
2894 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2895 silc_list_count(channel->user_list));
2896 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2898 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2899 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2901 silc_list_start(channel->user_list);
2902 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2904 n = chl->client->nickname;
2908 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2909 memcpy(name_list + (len - len2), n, len2);
2912 if (i == silc_list_count(channel->user_list) - 1)
2914 memcpy(name_list + len, ",", 1);
2920 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2921 silc_buffer_put(client_id_list, idp->data, idp->len);
2922 silc_buffer_pull(client_id_list, idp->len);
2923 silc_buffer_free(idp);
2925 /* Client's mode on channel */
2926 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2927 silc_buffer_pull(client_mode_list, 4);
2929 silc_buffer_push(client_id_list,
2930 client_id_list->data - client_id_list->head);
2931 silc_buffer_push(client_mode_list,
2932 client_mode_list->data - client_mode_list->head);
2937 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2938 SILC_STATUS_OK, 0, 4,
2942 4, client_id_list->data,
2943 client_id_list->len,
2944 5, client_mode_list->data,
2945 client_mode_list->len);
2946 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2947 packet->data, packet->len, FALSE);
2949 silc_buffer_free(packet);
2950 silc_free(name_list);
2951 silc_buffer_free(client_id_list);
2952 silc_buffer_free(client_mode_list);
2956 silc_server_command_free(cmd);