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. */
673 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
674 SILC_STATUS_ERR_NO_SUCH_NICK,
675 3, nick, strlen(nick));
679 /* Router always finds the client entry if it exists in the SILC network.
680 However, it might be incomplete entry and does not include all the
681 mandatory fields that WHOIS command reply requires. Check for these and
682 make query from the server who owns the client if some fields are
684 if (server->server_type == SILC_ROUTER &&
685 !silc_server_command_whois_check(cmd, clients, clients_count)) {
690 /* Send the command reply to the client */
691 silc_server_command_whois_send_reply(cmd, clients, clients_count);
697 silc_free(client_id);
701 silc_free(server_name);
706 /* Server side of command WHOIS. Processes user's query and sends found
707 results as command replies back to the client. */
709 SILC_SERVER_CMD_FUNC(whois)
711 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
714 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3);
716 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
717 ret = silc_server_command_whois_from_client(cmd);
719 ret = silc_server_command_whois_from_server(cmd);
722 silc_server_command_free(cmd);
725 SILC_SERVER_CMD_FUNC(whowas)
729 /******************************************************************************
733 ******************************************************************************/
736 silc_server_command_identify_parse(SilcServerCommandContext cmd,
737 SilcClientID **client_id,
744 unsigned int argc = silc_argument_get_arg_num(cmd->args);
746 /* If client ID is in the command it must be used instead of nickname */
747 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
749 /* No ID, get the nickname@server string and parse it. */
750 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
752 if (strchr(tmp, '@')) {
753 len = strcspn(tmp, "@");
754 *nickname = silc_calloc(len + 1, sizeof(char));
755 memcpy(*nickname, tmp, len);
756 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
757 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
759 *nickname = strdup(tmp);
762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
763 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
767 /* Command includes ID, use that */
768 *client_id = silc_id_payload_parse_id(tmp, len);
771 /* Get the max count of reply messages allowed */
773 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
776 SILC_STATUS_ERR_TOO_MANY_PARAMS);
778 silc_free(*nickname);
780 silc_free(*server_name);
790 /* Checks that all mandatory fields are present. If not then send WHOIS
791 request to the server who owns the client. We use WHOIS because we want
792 to get as much information as possible at once. */
795 silc_server_command_identify_check(SilcServerCommandContext cmd,
796 SilcClientEntry *clients,
797 unsigned int clients_count)
799 SilcServer server = cmd->server;
801 SilcClientEntry entry;
803 for (i = 0; i < clients_count; i++) {
806 if (!entry->nickname) {
808 unsigned short old_ident;
810 old_ident = silc_command_get_ident(cmd->payload);
811 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
812 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
813 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
815 /* Send WHOIS request. We send WHOIS since we're doing the requesting
816 now anyway so make it a good one. */
817 silc_server_packet_send(server, entry->router->connection,
818 SILC_PACKET_COMMAND, cmd->packet->flags,
819 tmpbuf->data, tmpbuf->len, TRUE);
821 /* Reprocess this packet after received reply */
822 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
823 silc_command_get_ident(cmd->payload),
824 silc_server_command_identify, (void *)cmd);
827 /* Put old data back to the Command Payload we just changed */
828 silc_command_set_ident(cmd->payload, old_ident);
829 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
831 silc_buffer_free(tmpbuf);
840 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
841 SilcClientEntry *clients,
842 unsigned int clients_count)
844 SilcServer server = cmd->server;
846 int i, count = 0, len;
847 SilcBuffer packet, idp;
848 SilcClientEntry entry;
849 SilcCommandStatus status;
850 unsigned short ident = silc_command_get_ident(cmd->payload);
852 status = SILC_STATUS_OK;
853 if (clients_count > 1)
854 status = SILC_STATUS_LIST_START;
856 for (i = 0; i < clients_count; i++) {
859 if (count && i - 1 == count)
862 if (clients_count > 2)
863 status = SILC_STATUS_LIST_ITEM;
865 if (clients_count > 1 && i == clients_count - 1)
866 status = SILC_STATUS_LIST_END;
868 /* Send IDENTIFY reply */
869 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
870 tmp = silc_argument_get_first_arg(cmd->args, NULL);
874 char nh[256], uh[256];
875 SilcSocketConnection hsock;
877 memset(uh, 0, sizeof(uh));
878 memset(nh, 0, sizeof(nh));
880 strncat(nh, entry->nickname, strlen(entry->nickname));
881 if (!strchr(entry->nickname, '@')) {
883 len = entry->router ? strlen(entry->router->server_name) :
884 strlen(server->server_name);
885 strncat(nh, entry->router ? entry->router->server_name :
886 server->server_name, len);
889 if (!entry->username) {
890 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
891 SILC_STATUS_OK, ident, 2,
892 2, idp->data, idp->len,
895 strncat(uh, entry->username, strlen(entry->username));
896 if (!strchr(entry->username, '@')) {
898 hsock = (SilcSocketConnection)entry->connection;
899 len = strlen(hsock->hostname);
900 strncat(uh, hsock->hostname, len);
903 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
904 SILC_STATUS_OK, ident, 3,
905 2, idp->data, idp->len,
910 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
911 0, packet->data, packet->len, FALSE);
913 silc_buffer_free(packet);
914 silc_buffer_free(idp);
920 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
922 SilcServer server = cmd->server;
923 char *nick = NULL, *server_name = NULL;
924 int count = 0, clients_count;
925 SilcClientID *client_id = NULL;
926 SilcClientEntry *clients = NULL, entry;
929 /* Parse the IDENTIFY request */
930 if (!silc_server_command_identify_parse(cmd, &client_id, &nick,
931 &server_name, &count))
934 /* Protocol dictates that we must always send the received IDENTIFY request
935 to our router if we are normal server, so let's do it now unless we
936 are standalone. We will not send any replies to the client until we
937 have received reply from the router. */
938 if (server->server_type == SILC_SERVER &&
939 !cmd->pending && !server->standalone) {
941 unsigned short old_ident;
943 old_ident = silc_command_get_ident(cmd->payload);
944 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
945 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
947 /* Send IDENTIFY command to our router */
948 silc_server_packet_send(server, (SilcSocketConnection)
949 server->router->connection,
950 SILC_PACKET_COMMAND, cmd->packet->flags,
951 tmpbuf->data, tmpbuf->len, TRUE);
953 /* Reprocess this packet after received reply from router */
954 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
955 silc_command_get_ident(cmd->payload),
956 silc_server_command_identify, (void *)cmd);
959 silc_command_set_ident(cmd->payload, old_ident);
961 silc_buffer_free(tmpbuf);
966 /* We are ready to process the command request. Let's search for the
967 requested client and send reply to the requesting client. */
969 /* Get all clients matching that ID or nickname from local list */
971 entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
973 clients = silc_calloc(1, sizeof(*clients));
978 clients = silc_idlist_get_clients_by_nickname(server->local_list,
983 /* Check global list as well */
986 entry = silc_idlist_find_client_by_id(server->global_list,
989 clients = silc_calloc(1, sizeof(*clients));
994 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1001 /* Such a client really does not exist in the SILC network. */
1002 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1003 SILC_STATUS_ERR_NO_SUCH_NICK,
1004 3, nick, strlen(nick));
1008 /* Check that all mandatory fields are present and request those data
1009 from the server who owns the client if necessary. */
1010 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1011 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1016 /* Send the command reply to the client */
1017 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1023 silc_free(client_id);
1027 silc_free(server_name);
1033 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1035 SilcServer server = cmd->server;
1036 char *nick = NULL, *server_name = NULL;
1037 int count = 0, clients_count;
1038 SilcClientID *client_id = NULL;
1039 SilcClientEntry *clients = NULL, entry;
1042 /* Parse the IDENTIFY request */
1043 if (!silc_server_command_identify_parse(cmd, &client_id, &nick,
1044 &server_name, &count))
1047 /* Process the command request. Let's search for the requested client and
1048 send reply to the requesting server. */
1051 entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
1053 clients = silc_calloc(1, sizeof(*clients));
1058 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1062 clients = silc_idlist_get_clients_by_hash(server->local_list,
1063 nick, server->md5hash,
1067 /* If we are router we will check our global list as well. */
1068 if (!clients && server->server_type == SILC_ROUTER) {
1070 entry = silc_idlist_find_client_by_id(server->global_list,
1073 clients = silc_calloc(1, sizeof(*clients));
1078 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1082 clients = silc_idlist_get_clients_by_hash(server->global_list,
1083 nick, server->md5hash,
1089 /* Such a client really does not exist in the SILC network. */
1090 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1091 SILC_STATUS_ERR_NO_SUCH_NICK,
1092 3, nick, strlen(nick));
1096 /* Check that all mandatory fields are present and request those data
1097 from the server who owns the client if necessary. */
1098 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1099 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1104 /* Send the command reply */
1105 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1111 silc_free(client_id);
1115 silc_free(server_name);
1120 SILC_SERVER_CMD_FUNC(identify)
1122 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1125 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3);
1127 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1128 ret = silc_server_command_identify_from_client(cmd);
1130 ret = silc_server_command_identify_from_server(cmd);
1133 silc_server_command_free(cmd);
1136 /* Checks string for bad characters and returns TRUE if they are found. */
1138 static int silc_server_command_bad_chars(char *nick)
1140 if (strchr(nick, '\\')) return TRUE;
1141 if (strchr(nick, '\"')) return TRUE;
1142 if (strchr(nick, '´')) return TRUE;
1143 if (strchr(nick, '`')) return TRUE;
1144 if (strchr(nick, '\'')) return TRUE;
1145 if (strchr(nick, '*')) return TRUE;
1146 if (strchr(nick, '/')) return TRUE;
1147 if (strchr(nick, '@')) return TRUE;
1152 /* Server side of command NICK. Sets nickname for user. Setting
1153 nickname causes generation of a new client ID for the client. The
1154 new client ID is sent to the client after changing the nickname. */
1156 SILC_SERVER_CMD_FUNC(nick)
1158 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1159 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1160 SilcServer server = cmd->server;
1161 SilcBuffer packet, nidp, oidp;
1162 SilcClientID *new_id;
1165 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1167 /* Check nickname */
1168 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1169 if (silc_server_command_bad_chars(nick) == TRUE) {
1170 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1171 SILC_STATUS_ERR_BAD_NICKNAME);
1175 /* Create new Client ID */
1176 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1177 cmd->server->md5hash, nick,
1180 /* Send notify about nickname change to our router. We send the new
1181 ID and ask to replace it with the old one. If we are router the
1182 packet is broadcasted. */
1183 if (!cmd->server->standalone)
1184 silc_server_send_replace_id(server, server->router->connection,
1185 server->server_type == SILC_SERVER ?
1186 FALSE : TRUE, client->id,
1187 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1188 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1190 /* Remove old cache entry */
1191 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1194 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1198 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1199 silc_free(client->id);
1202 /* Save the nickname as this client is our local client */
1203 if (client->nickname)
1204 silc_free(client->nickname);
1206 client->nickname = strdup(nick);
1207 client->id = new_id;
1209 /* Update client cache */
1210 silc_idcache_add(server->local_list->clients, client->nickname,
1211 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1213 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1215 /* Send NICK_CHANGE notify */
1216 silc_server_send_notify_on_channels(server, client,
1217 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1218 oidp->data, oidp->len,
1219 nidp->data, nidp->len);
1221 /* Send the new Client ID as reply command back to client */
1222 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1223 SILC_STATUS_OK, 0, 1,
1224 2, nidp->data, nidp->len);
1225 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1226 0, packet->data, packet->len, FALSE);
1228 silc_buffer_free(packet);
1229 silc_buffer_free(nidp);
1230 silc_buffer_free(oidp);
1233 silc_server_command_free(cmd);
1236 SILC_SERVER_CMD_FUNC(list)
1240 /* Server side of TOPIC command. Sets topic for channel and/or returns
1241 current topic to client. */
1243 SILC_SERVER_CMD_FUNC(topic)
1245 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1246 SilcServer server = cmd->server;
1247 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1248 SilcChannelID *channel_id;
1249 SilcChannelEntry channel;
1250 SilcChannelClientEntry chl;
1251 SilcBuffer packet, idp;
1253 unsigned int argc, tmp_len;
1255 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1257 argc = silc_argument_get_arg_num(cmd->args);
1259 /* Get Channel ID */
1260 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1263 SILC_STATUS_ERR_NO_CHANNEL_ID);
1266 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1268 /* Check whether the channel exists */
1269 channel = silc_idlist_find_channel_by_id(server->local_list,
1272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1273 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1279 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1282 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1286 if (strlen(tmp) > 256) {
1287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1288 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1292 /* See whether has rights to change topic */
1293 silc_list_start(channel->user_list);
1294 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1295 if (chl->client == client) {
1296 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1298 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1306 /* Set the topic for channel */
1308 silc_free(channel->topic);
1309 channel->topic = strdup(tmp);
1311 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1313 /* Send notify about topic change to all clients on the channel */
1314 silc_server_send_notify_to_channel(server, channel, TRUE,
1315 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1316 idp->data, idp->len,
1317 channel->topic, strlen(channel->topic));
1318 silc_buffer_free(idp);
1321 /* Send the topic to client as reply packet */
1322 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1324 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1325 SILC_STATUS_OK, 0, 2,
1326 2, idp->data, idp->len,
1328 strlen(channel->topic));
1330 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1331 SILC_STATUS_OK, 0, 1,
1332 2, idp->data, idp->len);
1333 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1334 0, packet->data, packet->len, FALSE);
1336 silc_buffer_free(packet);
1337 silc_buffer_free(idp);
1338 silc_free(channel_id);
1341 silc_server_command_free(cmd);
1344 /* Server side of INVITE command. Invites some client to join some channel. */
1346 SILC_SERVER_CMD_FUNC(invite)
1348 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1349 SilcServer server = cmd->server;
1350 SilcSocketConnection sock = cmd->sock, dest_sock;
1351 SilcClientEntry sender, dest;
1352 SilcClientID *dest_id;
1353 SilcChannelEntry channel;
1354 SilcChannelID *channel_id;
1359 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1361 /* Get destination ID */
1362 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1364 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1365 SILC_STATUS_ERR_NO_CLIENT_ID);
1368 dest_id = silc_id_payload_parse_id(tmp, len);
1370 /* Get Channel ID */
1371 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1374 SILC_STATUS_ERR_NO_CHANNEL_ID);
1377 channel_id = silc_id_payload_parse_id(tmp, len);
1379 /* Check whether the channel exists */
1380 channel = silc_idlist_find_channel_by_id(server->local_list,
1383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1384 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1388 /* Check whether the sender of this command is on the channel. */
1389 sender = (SilcClientEntry)sock->user_data;
1390 if (!silc_server_client_on_channel(sender, channel)) {
1391 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1392 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1396 /* Check whether the channel is invite-only channel. If yes then the
1397 sender of this command must be at least channel operator. */
1398 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1399 SilcChannelClientEntry chl;
1401 silc_list_start(channel->user_list);
1402 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1403 if (chl->client == sender) {
1404 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1406 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1413 /* Find the connection data for the destination. If it is local we will
1414 send it directly otherwise we will send it to router for routing. */
1415 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1417 dest_sock = (SilcSocketConnection)dest->connection;
1419 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1421 /* Check whether the requested client is already on the channel. */
1422 /* XXX if we are normal server we don't know about global clients on
1423 the channel thus we must request it (NAMES command), check from
1424 local cache as well. */
1425 if (silc_server_client_on_channel(dest, channel)) {
1426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1427 SILC_STATUS_ERR_USER_ON_CHANNEL);
1431 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1433 /* Send notify to the client that is invited to the channel */
1434 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1435 SILC_NOTIFY_TYPE_INVITE, 2,
1436 sidp->data, sidp->len, tmp, len);
1438 /* Send command reply */
1439 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1442 silc_buffer_free(sidp);
1445 silc_server_command_free(cmd);
1448 /* Quits connection to client. This gets called if client won't
1449 close the connection even when it has issued QUIT command. */
1451 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1453 SilcServer server = (SilcServer)context;
1454 SilcSocketConnection sock = server->sockets[fd];
1456 /* Free all client specific data, such as client entry and entires
1457 on channels this client may be on. */
1458 silc_server_free_sock_user_data(server, sock);
1460 /* Close the connection on our side */
1461 silc_server_close_connection(server, sock);
1464 /* Quits SILC session. This is the normal way to disconnect client. */
1466 SILC_SERVER_CMD_FUNC(quit)
1468 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1469 SilcServer server = cmd->server;
1470 SilcSocketConnection sock = cmd->sock;
1472 SILC_LOG_DEBUG(("Start"));
1474 /* We quit the connection with little timeout */
1475 silc_task_register(server->timeout_queue, sock->sock,
1476 silc_server_command_quit_cb, server,
1477 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1479 silc_server_command_free(cmd);
1482 SILC_SERVER_CMD_FUNC(kill)
1486 /* Server side of command INFO. This sends information about us to
1487 the client. If client requested specific server we will send the
1488 command to that server. */
1490 SILC_SERVER_CMD_FUNC(info)
1492 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1493 SilcServer server = cmd->server;
1494 SilcBuffer packet, idp;
1495 char info_string[256], *dest_server;
1497 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1499 /* Get server name */
1500 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1502 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1503 SILC_STATUS_ERR_NO_SUCH_SERVER);
1507 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1508 /* Send our reply */
1509 memset(info_string, 0, sizeof(info_string));
1510 snprintf(info_string, sizeof(info_string),
1511 "location: %s server: %s admin: %s <%s>",
1512 server->config->admin_info->location,
1513 server->config->admin_info->server_type,
1514 server->config->admin_info->admin_name,
1515 server->config->admin_info->admin_email);
1517 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1519 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1520 SILC_STATUS_OK, 0, 2,
1521 2, idp->data, idp->len,
1523 strlen(info_string));
1524 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1525 packet->data, packet->len, FALSE);
1527 silc_buffer_free(packet);
1528 silc_buffer_free(idp);
1530 /* Send this command to the requested server */
1532 if (server->server_type == SILC_SERVER && !server->standalone) {
1536 if (server->server_type == SILC_ROUTER) {
1542 silc_server_command_free(cmd);
1545 SILC_SERVER_CMD_FUNC(connect)
1549 /* Server side of command PING. This just replies to the ping. */
1551 SILC_SERVER_CMD_FUNC(ping)
1553 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1554 SilcServer server = cmd->server;
1559 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1562 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1565 SILC_STATUS_ERR_NO_SERVER_ID);
1568 id = silc_id_str2id(tmp, SILC_ID_SERVER);
1572 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1573 /* Send our reply */
1574 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1577 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1578 SILC_STATUS_ERR_NO_SUCH_SERVER);
1585 silc_server_command_free(cmd);
1588 SILC_SERVER_CMD_FUNC(oper)
1597 SilcChannelEntry channel;
1599 SilcClientEntry client;
1600 } JoinInternalContext;
1602 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1604 JoinInternalContext *ctx = (JoinInternalContext *)context;
1606 if (ctx->channel->key && ctx->channel->key_len) {
1609 clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1611 silc_server_send_notify_to_channel(ctx->server, ctx->channel, FALSE,
1612 SILC_NOTIFY_TYPE_JOIN, 1,
1613 clidp->data, clidp->len);
1615 /* Send NEW_CHANNEL_USER packet to primary route */
1616 silc_server_send_new_channel_user(server, server->router->connection,
1617 server->server_type == SILC_SERVER ?
1619 channel->id, SILC_ID_CHANNEL_LEN,
1620 client->id, SILC_ID_CLIENT_LEN);
1623 /* Send NAMES command reply to the joined channel so the user sees who
1624 is currently on the channel. */
1625 silc_server_command_send_names(ctx->server, ctx->client->connection,
1628 silc_buffer_free(clidp);
1631 silc_task_register(ctx->server->timeout_queue, fd,
1632 silc_server_command_join_notify, context,
1633 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1637 /* Assembles NAMES command and executes it. This is called when client
1638 joins to a channel and we wan't to send NAMES command reply to the
1641 void silc_server_command_send_names(SilcServer server,
1642 SilcSocketConnection sock,
1643 SilcChannelEntry channel)
1645 SilcServerCommandContext cmd;
1646 SilcBuffer buffer, idp;
1648 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1649 buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1650 1, idp->data, idp->len);
1652 cmd = silc_calloc(1, sizeof(*cmd));
1653 cmd->payload = silc_command_payload_parse(buffer);
1654 cmd->args = silc_command_get_args(cmd->payload);
1655 cmd->server = server;
1657 cmd->pending = FALSE;
1659 silc_server_command_names((void *)cmd);
1664 /* Internal routine that is called after router has replied to server's
1665 JOIN command it forwarded to the router. The route has joined and possibly
1666 creaetd the channel. This function adds the client to the channel's user
1669 SILC_SERVER_CMD_FUNC(add_to_channel)
1671 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1672 SilcServer server = cmd->server;
1673 SilcClientEntry client;
1674 SilcChannelEntry channel;
1675 SilcChannelClientEntry chl;
1678 /* Get channel name */
1679 channel_name = silc_argument_get_arg_type(cmd->args, 1, NULL);
1681 /* Get client entry */
1682 client = (SilcClientEntry)cmd->sock->user_data;
1684 /* Get channel entry */
1685 channel = silc_idlist_find_channel_by_name(server->local_list,
1686 channel_name, NULL);
1688 /* Join the client to the channel by adding it to channel's user list.
1689 Add also the channel to client entry's channels list for fast cross-
1691 chl = silc_calloc(1, sizeof(*chl));
1692 //chl->mode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
1693 chl->client = client;
1694 chl->channel = channel;
1695 silc_list_add(channel->user_list, chl);
1696 silc_list_add(client->channels, chl);
1699 silc_server_command_free(cmd);
1702 /* Internal routine to join channel. The channel sent to this function
1703 has been either created or resolved from ID lists. This joins the sent
1704 client to the channel. */
1706 static void silc_server_command_join_channel(SilcServer server,
1707 SilcServerCommandContext cmd,
1708 SilcChannelEntry channel,
1712 SilcSocketConnection sock = cmd->sock;
1714 unsigned int tmp_len;
1715 unsigned char *passphrase = NULL, mode[4];
1716 SilcClientEntry client;
1717 SilcChannelClientEntry chl;
1718 SilcBuffer reply, chidp, clidp;
1720 SILC_LOG_DEBUG(("Start"));
1725 /* Get passphrase */
1726 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1728 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1729 memcpy(passphrase, tmp, tmp_len);
1733 * Check channel modes
1736 /* Check invite list if channel is invite-only channel */
1737 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1738 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1739 /* Invite list is specified. Check whether client is invited in the
1740 list. If not, then check whether it has been invited otherwise. */
1743 /* XXX client must be invited to be able to join the channel */
1747 /* Check ban list if set */
1748 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1752 /* Check the channel passphrase if set. */
1753 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1754 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1755 strlen(channel->mode_data.passphrase))) {
1756 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1757 SILC_STATUS_ERR_BAD_PASSWORD);
1762 /* Check user count limit if set. */
1763 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1764 if (silc_list_count(channel->user_list) + 1 >
1765 channel->mode_data.user_limit) {
1766 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1767 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1773 * Client is allowed to join to the channel. Make it happen.
1776 /* If the JOIN request was forwarded to us we will make a bit slower
1777 query to get the client pointer. Otherwise, we get the client pointer
1779 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1780 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1781 client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
1784 SILC_LOG_ERROR(("Forwarded join command did not find the client who "
1785 "wanted to join the channel"));
1790 client = (SilcClientEntry)sock->user_data;
1793 /* Check whether the client already is on the channel */
1794 if (silc_server_client_on_channel(client, channel)) {
1795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1796 SILC_STATUS_ERR_USER_ON_CHANNEL);
1800 /* Generate new channel key as protocol dictates */
1802 silc_server_create_channel_key(server, channel, 0);
1804 /* Join the client to the channel by adding it to channel's user list.
1805 Add also the channel to client entry's channels list for fast cross-
1807 chl = silc_calloc(1, sizeof(*chl));
1809 chl->client = client;
1810 chl->channel = channel;
1811 silc_list_add(channel->user_list, chl);
1812 silc_list_add(client->channels, chl);
1814 /* Encode Client ID Payload of the original client who wants to join */
1815 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1817 /* Encode command reply packet */
1818 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1819 SILC_PUT32_MSB(channel->mode, mode);
1820 if (!channel->topic) {
1822 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1823 SILC_STATUS_OK, 0, 3,
1824 2, channel->channel_name,
1825 strlen(channel->channel_name),
1826 3, chidp->data, chidp->len,
1830 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1831 SILC_STATUS_OK, 0, 4,
1832 2, channel->channel_name,
1833 strlen(channel->channel_name),
1834 3, chidp->data, chidp->len,
1837 strlen(channel->topic));
1840 if (server->server_type == SILC_ROUTER &&
1841 cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1842 /* We are router and server has forwarded this command to us. Send
1843 all replys to the server. */
1846 /* Send command reply destined to the original client */
1847 tmpid = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1848 silc_server_packet_send_dest(cmd->server, sock,
1849 SILC_PACKET_COMMAND_REPLY, 0,
1850 tmpid, cmd->packet->src_id_type,
1851 reply->data, reply->len, FALSE);
1853 /* Distribute new channel key to local cell and local clients. */
1854 silc_server_send_channel_key(server, channel, FALSE);
1856 /* Distribute JOIN notify into the cell for everbody on the channel */
1857 silc_server_send_notify_to_channel(server, channel, FALSE,
1858 SILC_NOTIFY_TYPE_JOIN, 1,
1859 clidp->data, clidp->len);
1861 /* Broadcast NEW_CHANNEL_USER packet to primary route */
1862 silc_server_send_new_channel_user(server, server->router->connection,
1863 TRUE, channel->id, SILC_ID_CHANNEL_LEN,
1864 client->id, SILC_ID_CLIENT_LEN);
1868 /* Client sent the command. Send all replies directly to the client. */
1870 /* Send command reply */
1871 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1872 reply->data, reply->len, FALSE);
1874 /* Send the channel key. Channel key is sent before any other packet
1876 silc_server_send_channel_key(server, channel, server->standalone ?
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 (!server->standalone)
1886 silc_server_send_new_channel_user(server, server->router->connection,
1888 channel->id, SILC_ID_CHANNEL_LEN,
1889 client->id, SILC_ID_CLIENT_LEN);
1891 /* Send NAMES command reply to the joined channel so the user sees who
1892 is currently on the channel. */
1893 silc_server_command_send_names(server, sock, channel);
1896 silc_buffer_free(reply);
1897 silc_buffer_free(clidp);
1898 silc_buffer_free(chidp);
1902 silc_free(passphrase);
1905 /* Server side of command JOIN. Joins client into requested channel. If
1906 the channel does not exist it will be created. */
1908 SILC_SERVER_CMD_FUNC(join)
1910 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1911 SilcServer server = cmd->server;
1913 char *tmp, *channel_name = NULL, *cipher = NULL;
1914 SilcChannelEntry channel;
1915 unsigned int umode = 0;
1916 int created = FALSE;
1918 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 3);
1920 /* Get channel name */
1921 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1924 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1929 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1931 SILC_STATUS_ERR_BAD_CHANNEL);
1932 silc_free(channel_name);
1936 /* Get cipher name */
1937 cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1939 /* See if the channel exists */
1940 channel = silc_idlist_find_channel_by_name(server->local_list,
1941 channel_name, NULL);
1943 /* Channel not found */
1945 /* If we are standalone server we don't have a router, we just create
1946 the channel by ourselves. */
1947 if (server->standalone) {
1948 channel = silc_server_create_new_channel(server, server->id, cipher,
1950 umode |= SILC_CHANNEL_UMODE_CHANOP;
1951 umode |= SILC_CHANNEL_UMODE_CHANFO;
1955 /* The channel does not exist on our server. If we are normal server
1956 we will send JOIN command to our router which will handle the joining
1957 procedure (either creates the channel if it doesn't exist or joins
1958 the client to it). */
1959 if (server->server_type == SILC_SERVER) {
1960 /* Forward the original JOIN command to the router */
1961 silc_buffer_push(cmd->packet->buffer,
1962 cmd->packet->buffer->data -
1963 cmd->packet->buffer->head);
1964 silc_server_packet_forward(server, (SilcSocketConnection)
1965 server->router->connection,
1966 cmd->packet->buffer->data,
1967 cmd->packet->buffer->len, TRUE);
1969 /* Register handler that will be called after the router has replied
1970 to us. We will add the client to the new channel in this callback
1971 function. Will be called from JOIN command reply. */
1972 silc_server_command_pending(server, SILC_COMMAND_JOIN,
1973 ++server->router->data.cmd_ident,
1974 silc_server_command_add_to_channel,
1979 /* We are router and the channel does not seem exist so we will check
1980 our global list as well for the channel. */
1981 channel = silc_idlist_find_channel_by_name(server->global_list,
1982 channel_name, NULL);
1984 /* Channel really does not exist, create it */
1985 channel = silc_server_create_new_channel(server, server->id, cipher,
1987 umode |= SILC_CHANNEL_UMODE_CHANOP;
1988 umode |= SILC_CHANNEL_UMODE_CHANFO;
1994 /* Join to the channel */
1995 silc_server_command_join_channel(server, cmd, channel, created, umode);
1998 silc_server_command_free(cmd);
2001 /* Server side of command MOTD. Sends server's current "message of the
2002 day" to the client. */
2004 SILC_SERVER_CMD_FUNC(motd)
2006 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2007 SilcServer server = cmd->server;
2011 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2013 /* XXX show currently only our motd */
2015 if (server->config && server->config->motd &&
2016 server->config->motd->motd_file) {
2019 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2024 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2035 silc_server_command_free(cmd);
2038 SILC_SERVER_CMD_FUNC(umode)
2042 /* Checks that client has rights to add or remove channel modes. If any
2043 of the checks fails FALSE is returned. */
2045 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2046 SilcChannelClientEntry client,
2049 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2050 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2052 /* Check whether has rights to change anything */
2053 if (!is_op && !is_fo)
2056 /* Check whether has rights to change everything */
2060 /* We know that client is channel operator, check that they are not
2061 changing anything that requires channel founder rights. Rest of the
2062 modes are available automatically for channel operator. */
2064 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2065 if (is_op && !is_fo)
2068 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2069 if (is_op && !is_fo)
2074 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2075 if (is_op && !is_fo)
2078 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2079 if (is_op && !is_fo)
2084 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2085 if (is_op && !is_fo)
2088 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2089 if (is_op && !is_fo)
2097 /* Server side command of CMODE. Changes channel mode */
2099 SILC_SERVER_CMD_FUNC(cmode)
2101 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2102 SilcServer server = cmd->server;
2103 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2104 SilcChannelID *channel_id;
2105 SilcChannelEntry channel;
2106 SilcChannelClientEntry chl;
2107 SilcBuffer packet, cidp;
2108 unsigned char *tmp, *tmp_id, *tmp_mask;
2109 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2111 SILC_LOG_DEBUG(("Start"));
2113 argc = silc_argument_get_arg_num(cmd->args);
2115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2116 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2121 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2125 /* Get Channel ID */
2126 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2128 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2129 SILC_STATUS_ERR_NO_CHANNEL_ID);
2132 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2134 /* Get the channel mode mask */
2135 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2137 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2138 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2141 SILC_GET32_MSB(mode_mask, tmp_mask);
2143 /* Get channel entry */
2144 channel = silc_idlist_find_channel_by_id(server->local_list,
2147 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2148 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2152 /* Check whether this client is on the channel */
2153 if (!silc_server_client_on_channel(client, channel)) {
2154 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2155 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2159 /* Get entry to the channel user list */
2160 silc_list_start(channel->user_list);
2161 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2162 if (chl->client == client)
2165 /* Check that client has rights to change any requested channel modes */
2166 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2168 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2173 * Check the modes. Modes that requires nothing special operation are
2177 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2178 /* Channel uses private keys to protect traffic. Client(s) has set the
2179 key locally they want to use, server does not know that key. */
2180 /* Nothing interesting to do here now */
2182 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2183 /* The mode is removed and we need to generate and distribute
2184 new channel key. Clients are not using private channel keys
2185 anymore after this. */
2187 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2190 /* Re-generate channel key */
2191 silc_server_create_channel_key(server, channel, 0);
2193 /* Encode channel key payload to be distributed on the channel */
2195 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2196 strlen(channel->channel_key->
2198 channel->channel_key->cipher->name,
2199 channel->key_len / 8, channel->key);
2201 /* If we are normal server then we will send it to our router. If we
2202 are router we will send it to all local servers that has clients on
2204 if (server->server_type == SILC_SERVER) {
2205 if (!server->standalone)
2206 silc_server_packet_send(server,
2207 cmd->server->router->connection,
2208 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2214 /* Send to locally connected clients on the channel */
2215 silc_server_packet_send_local_channel(server, channel,
2216 SILC_PACKET_CHANNEL_KEY, 0,
2217 packet->data, packet->len, FALSE);
2218 silc_buffer_free(packet);
2222 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2223 /* User limit is set on channel */
2224 unsigned int user_limit;
2226 /* Get user limit */
2227 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2229 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2231 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2235 SILC_GET32_MSB(user_limit, tmp);
2236 channel->mode_data.user_limit = user_limit;
2239 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2240 /* User limit mode is unset. Remove user limit */
2241 channel->mode_data.user_limit = 0;
2244 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2245 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2246 /* Passphrase has been set to channel */
2248 /* Get the passphrase */
2249 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2251 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2252 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2256 /* Save the passphrase */
2257 channel->mode_data.passphrase = strdup(tmp);
2260 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2261 /* Passphrase mode is unset. remove the passphrase */
2262 if (channel->mode_data.passphrase) {
2263 silc_free(channel->mode_data.passphrase);
2264 channel->mode_data.passphrase = NULL;
2269 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2270 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2271 /* Ban list is specified for channel */
2274 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2277 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2281 /* XXX check that channel founder is not banned */
2283 /* Save the ban list */
2284 channel->mode_data.ban_list = strdup(tmp);
2287 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2288 /* Ban mode is unset. Remove the entire ban list */
2289 if (channel->mode_data.ban_list) {
2290 silc_free(channel->mode_data.ban_list);
2291 channel->mode_data.ban_list = NULL;
2296 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2297 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2298 /* Invite list is specified for channel */
2300 /* Get invite list */
2301 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2303 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2304 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2308 /* Save the invite linst */
2309 channel->mode_data.invite_list = strdup(tmp);
2312 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2313 /* Invite list mode is unset. Remove the entire invite list */
2314 if (channel->mode_data.invite_list) {
2315 silc_free(channel->mode_data.invite_list);
2316 channel->mode_data.invite_list = NULL;
2321 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2322 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2323 /* Cipher to use protect the traffic */
2324 unsigned int key_len = 128;
2328 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2331 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2335 cp = strchr(tmp, ':');
2341 /* XXX Duplicated code, make own function for this!! */
2343 /* Delete old cipher and allocate the new one */
2344 silc_cipher_free(channel->channel_key);
2345 silc_cipher_alloc(tmp, &channel->channel_key);
2351 /* Re-generate channel key */
2352 silc_server_create_channel_key(server, channel, key_len);
2354 /* Encode channel key payload to be distributed on the channel */
2356 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2357 strlen(channel->channel_key->
2359 channel->channel_key->cipher->name,
2360 channel->key_len / 8, channel->key);
2362 /* If we are normal server then we will send it to our router. If we
2363 are router we will send it to all local servers that has clients on
2365 if (server->server_type == SILC_SERVER) {
2366 if (!server->standalone)
2367 silc_server_packet_send(server,
2368 cmd->server->router->connection,
2369 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2375 /* Send to locally connected clients on the channel */
2376 silc_server_packet_send_local_channel(server, channel,
2377 SILC_PACKET_CHANNEL_KEY, 0,
2378 packet->data, packet->len, FALSE);
2379 silc_buffer_free(packet);
2382 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2383 /* Cipher mode is unset. Remove the cipher and revert back to
2386 if (channel->mode_data.cipher) {
2387 silc_free(channel->mode_data.cipher);
2388 channel->mode_data.cipher = NULL;
2389 channel->mode_data.key_len = 0;
2392 /* Generate new cipher and key for the channel */
2394 /* XXX Duplicated code, make own function for this!! */
2396 /* Delete old cipher and allocate default one */
2397 silc_cipher_free(channel->channel_key);
2398 if (!channel->cipher)
2399 silc_cipher_alloc("twofish", &channel->channel_key);
2401 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2403 /* Re-generate channel key */
2404 silc_server_create_channel_key(server, channel, 0);
2406 /* Encode channel key payload to be distributed on the channel */
2408 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2409 strlen(channel->channel_key->
2411 channel->channel_key->cipher->name,
2412 channel->key_len / 8, channel->key);
2414 /* If we are normal server then we will send it to our router. If we
2415 are router we will send it to all local servers that has clients on
2417 if (server->server_type == SILC_SERVER) {
2418 if (!server->standalone)
2419 silc_server_packet_send(server,
2420 cmd->server->router->connection,
2421 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2427 /* Send to locally connected clients on the channel */
2428 silc_server_packet_send_local_channel(server, channel,
2429 SILC_PACKET_CHANNEL_KEY, 0,
2430 packet->data, packet->len, FALSE);
2431 silc_buffer_free(packet);
2435 /* Finally, set the mode */
2436 channel->mode = mode_mask;
2438 /* Send CMODE_CHANGE notify */
2439 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2440 silc_server_send_notify_to_channel(server, channel, TRUE,
2441 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2442 cidp->data, cidp->len,
2446 /* Send command reply to sender */
2447 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2448 SILC_STATUS_OK, 0, 1,
2450 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2451 packet->data, packet->len, FALSE);
2453 silc_buffer_free(packet);
2454 silc_free(channel_id);
2457 silc_server_command_free(cmd);
2460 /* Server side of CUMODE command. Changes client's mode on a channel. */
2462 SILC_SERVER_CMD_FUNC(cumode)
2464 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2465 SilcServer server = cmd->server;
2466 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2467 SilcChannelID *channel_id;
2468 SilcClientID *client_id;
2469 SilcChannelEntry channel;
2470 SilcClientEntry target_client;
2471 SilcChannelClientEntry chl;
2472 SilcBuffer packet, idp;
2473 unsigned char *tmp_id, *tmp_mask;
2474 unsigned int target_mask, sender_mask, tmp_len;
2477 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2479 /* Get Channel ID */
2480 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2483 SILC_STATUS_ERR_NO_CHANNEL_ID);
2486 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2488 /* Get channel entry */
2489 channel = silc_idlist_find_channel_by_id(server->local_list,
2492 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2493 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2497 /* Check whether sender is on the channel */
2498 if (!silc_server_client_on_channel(client, channel)) {
2499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2500 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2504 /* Check that client has rights to change other's rights */
2505 silc_list_start(channel->user_list);
2506 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2507 if (chl->client == client) {
2508 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2509 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2511 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2515 sender_mask = chl->mode;
2520 /* Get the target client's channel mode mask */
2521 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2523 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2524 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2527 SILC_GET32_MSB(target_mask, tmp_mask);
2529 /* Get target Client ID */
2530 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2533 SILC_STATUS_ERR_NO_CHANNEL_ID);
2536 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2538 /* Get target client's entry */
2539 target_client = silc_idlist_find_client_by_id(server->local_list,
2541 if (!target_client) {
2542 /* XXX If target client is not one of mine send to primary route */
2545 /* Check whether target client is on the channel */
2546 if (!silc_server_client_on_channel(target_client, channel)) {
2547 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2548 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2552 /* Get entry to the channel user list */
2553 silc_list_start(channel->user_list);
2554 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2555 if (chl->client == target_client)
2562 /* If the target client is founder, no one else can change their mode
2564 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2565 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2566 SILC_STATUS_ERR_NOT_YOU);
2570 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2571 /* Cannot promote anyone to channel founder */
2572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2573 SILC_STATUS_ERR_NOT_YOU);
2576 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2577 if (target_client == client) {
2578 /* Remove channel founder rights from itself */
2579 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2582 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2583 SILC_STATUS_ERR_NOT_YOU);
2589 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2590 /* Promote to operator */
2591 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2592 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2596 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2597 /* Demote to normal user */
2598 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2603 /* Send notify to channel, notify only if mode was actually changed. */
2605 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2606 silc_server_send_notify_to_channel(server, channel, TRUE,
2607 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2608 idp->data, idp->len,
2609 tmp_mask, 4, tmp_id, tmp_len);
2610 silc_buffer_free(idp);
2613 /* Send command reply to sender */
2614 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2615 SILC_STATUS_OK, 0, 2,
2617 3, tmp_id, tmp_len);
2618 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2619 packet->data, packet->len, FALSE);
2621 silc_buffer_free(packet);
2622 silc_free(channel_id);
2623 silc_free(client_id);
2626 silc_server_command_free(cmd);
2629 /* Server side of KICK command. Kicks client out of channel. */
2631 SILC_SERVER_CMD_FUNC(kick)
2635 SILC_SERVER_CMD_FUNC(restart)
2639 SILC_SERVER_CMD_FUNC(close)
2643 SILC_SERVER_CMD_FUNC(die)
2647 SILC_SERVER_CMD_FUNC(silcoper)
2651 /* Server side command of LEAVE. Removes client from a channel. */
2653 SILC_SERVER_CMD_FUNC(leave)
2655 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2656 SilcServer server = cmd->server;
2657 SilcSocketConnection sock = cmd->sock;
2658 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2660 SilcChannelEntry channel;
2662 unsigned int i, len;
2665 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2667 /* Get Channel ID */
2668 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2671 SILC_STATUS_ERR_NO_CHANNEL_ID);
2674 id = silc_id_payload_parse_id(tmp, len);
2676 /* Get channel entry */
2677 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2680 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2684 /* Check whether this client is on the channel */
2685 if (!silc_server_client_on_channel(id_entry, channel)) {
2686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2687 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2691 /* Notify routers that they should remove this client from their list
2692 of clients on the channel. */
2693 if (!server->standalone)
2694 silc_server_send_remove_channel_user(server,
2695 server->router->connection,
2696 server->server_type == SILC_ROUTER ?
2697 TRUE : FALSE, id_entry->id, id);
2699 /* Remove client from channel */
2700 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2702 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2705 /* If the channel does not exist anymore we won't send anything */
2709 /* Re-generate channel key */
2710 silc_server_create_channel_key(server, channel, 0);
2712 /* Encode channel key payload to be distributed on the channel */
2714 silc_channel_key_payload_encode(len, tmp,
2715 strlen(channel->channel_key->cipher->name),
2716 channel->channel_key->cipher->name,
2717 channel->key_len / 8, channel->key);
2719 /* If we are normal server then we will send it to our router. If we
2720 are router we will send it to all local servers that has clients on
2722 if (server->server_type == SILC_SERVER) {
2723 if (!server->standalone)
2724 silc_server_packet_send(server,
2725 cmd->server->router->connection,
2726 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2732 /* Send to locally connected clients on the channel */
2733 silc_server_packet_send_local_channel(server, channel,
2734 SILC_PACKET_CHANNEL_KEY, 0,
2735 packet->data, packet->len, FALSE);
2737 silc_buffer_free(packet);
2741 silc_server_command_free(cmd);
2744 /* Server side of command NAMES. Resolves clients and their names currently
2745 joined on the requested channel. The name list is sent back to the
2748 SILC_SERVER_CMD_FUNC(names)
2750 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2751 SilcServer server = cmd->server;
2752 SilcChannelEntry channel;
2753 SilcChannelClientEntry chl;
2756 unsigned int i, len, len2, tmp_len;
2758 char *name_list = NULL, *n;
2759 SilcBuffer client_id_list;
2760 SilcBuffer client_mode_list;
2762 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NAMES, cmd, 1, 2);
2764 /* Get Channel ID */
2765 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2768 SILC_STATUS_ERR_NO_CHANNEL_ID);
2771 id = silc_id_payload_parse_id(tmp, tmp_len);
2773 /* Check whether the channel exists. If we are normal server and the
2774 channel does not exist we will send this same command to our router
2775 which will know if the channel exists. */
2776 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2778 if (server->server_type == SILC_SERVER && !server->standalone) {
2779 /* XXX Send names command */
2781 cmd->pending = TRUE;
2782 silc_server_command_pending(server, SILC_COMMAND_NAMES, 0,
2783 silc_server_command_names, context);
2787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2788 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2792 /* Assemble the name list now */
2795 silc_list_start(channel->user_list);
2797 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2798 n = chl->client->nickname;
2802 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2803 memcpy(name_list + (len - len2), n, len2);
2806 if (i == silc_list_count(channel->user_list) - 1)
2808 memcpy(name_list + len, ",", 1);
2816 /* Assemble the Client ID list now */
2817 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2818 silc_list_count(channel->user_list));
2819 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2820 silc_list_start(channel->user_list);
2821 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2824 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2825 silc_buffer_format(client_id_list,
2826 SILC_STR_UI_XNSTRING(idp->data, idp->len),
2828 silc_buffer_pull(client_id_list, idp->len);
2829 silc_buffer_free(idp);
2831 silc_buffer_push(client_id_list,
2832 client_id_list->data - client_id_list->head);
2834 /* Assemble mode list */
2835 client_mode_list = silc_buffer_alloc(4 *
2836 silc_list_count(channel->user_list));
2837 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2838 silc_list_start(channel->user_list);
2839 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2840 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2841 silc_buffer_pull(client_mode_list, 4);
2843 silc_buffer_push(client_mode_list,
2844 client_mode_list->data - client_mode_list->head);
2847 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2848 SILC_STATUS_OK, 0, 4,
2852 4, client_id_list->data,
2853 client_id_list->len,
2854 5, client_mode_list->data,
2855 client_mode_list->len);
2856 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2857 packet->data, packet->len, FALSE);
2859 silc_buffer_free(packet);
2860 silc_free(name_list);
2861 silc_buffer_free(client_id_list);
2862 silc_buffer_free(client_mode_list);
2866 silc_server_command_free(cmd);