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_users(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(users, USERS, 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,
316 unsigned int *client_id_count,
324 unsigned int argc = silc_argument_get_arg_num(cmd->args);
327 /* If client ID is in the command it must be used instead of nickname */
328 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
330 /* No ID, get the nickname@server string and parse it. */
331 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
333 if (strchr(tmp, '@')) {
334 len = strcspn(tmp, "@");
335 *nickname = silc_calloc(len + 1, sizeof(char));
336 memcpy(*nickname, tmp, len);
337 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
338 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
340 *nickname = strdup(tmp);
343 silc_server_command_send_status_reply(cmd, command,
344 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
348 /* Command includes ID, we must use that. Also check whether the command
349 has more than one ID set - take them all. */
351 *client_id = silc_calloc(1, sizeof(**client_id));
352 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
353 *client_id_count = 1;
355 /* Take all ID's from the command packet */
357 for (k = 1, i = 4; i < argc; i++) {
358 tmp = silc_argument_get_arg_type(cmd->args, i, &len);
360 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
361 (*client_id_count + 1));
362 (*client_id)[k++] = silc_id_payload_parse_id(tmp, len);
363 (*client_id_count)++;
368 /* Command includes ID, use that */
371 /* Get the max count of reply messages allowed */
372 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
382 silc_server_command_whois_check(SilcServerCommandContext cmd,
383 SilcClientEntry *clients,
384 unsigned int clients_count)
386 SilcServer server = cmd->server;
388 SilcClientEntry entry;
390 for (i = 0; i < clients_count; i++) {
393 if (!entry->nickname || !entry->username || !entry->userinfo) {
395 unsigned short old_ident;
397 old_ident = silc_command_get_ident(cmd->payload);
398 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
399 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
401 /* Send WHOIS command */
402 silc_server_packet_send(server, entry->router->connection,
403 SILC_PACKET_COMMAND, cmd->packet->flags,
404 tmpbuf->data, tmpbuf->len, TRUE);
406 /* Reprocess this packet after received reply */
407 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
408 silc_command_get_ident(cmd->payload),
409 silc_server_command_whois, (void *)cmd);
412 silc_command_set_ident(cmd->payload, old_ident);
414 silc_buffer_free(tmpbuf);
423 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
424 SilcClientEntry *clients,
425 unsigned int clients_count)
427 SilcServer server = cmd->server;
429 int i, count = 0, len;
430 SilcBuffer packet, idp;
431 SilcClientEntry entry;
432 SilcCommandStatus status;
433 unsigned short ident = silc_command_get_ident(cmd->payload);
435 status = SILC_STATUS_OK;
436 if (clients_count > 1)
437 status = SILC_STATUS_LIST_START;
439 for (i = 0; i < clients_count; i++) {
442 if (count && i - 1 == count)
445 if (clients_count > 2)
446 status = SILC_STATUS_LIST_ITEM;
448 if (clients_count > 1 && i == clients_count - 1)
449 status = SILC_STATUS_LIST_END;
451 /* Send WHOIS reply */
452 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
453 tmp = silc_argument_get_first_arg(cmd->args, NULL);
457 char nh[256], uh[256];
458 unsigned char idle[4];
459 SilcSocketConnection hsock;
461 memset(uh, 0, sizeof(uh));
462 memset(nh, 0, sizeof(nh));
464 strncat(nh, entry->nickname, strlen(entry->nickname));
465 if (!strchr(entry->nickname, '@')) {
467 len = entry->router ? strlen(entry->router->server_name) :
468 strlen(server->server_name);
469 strncat(nh, entry->router ? entry->router->server_name :
470 server->server_name, len);
473 strncat(uh, entry->username, strlen(entry->username));
474 if (!strchr(entry->username, '@')) {
476 hsock = (SilcSocketConnection)entry->connection;
477 len = strlen(hsock->hostname);
478 strncat(uh, hsock->hostname, len);
481 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
486 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
488 2, idp->data, idp->len,
492 strlen(entry->userinfo),
496 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
498 2, idp->data, idp->len,
504 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
505 0, packet->data, packet->len, FALSE);
507 silc_buffer_free(packet);
508 silc_buffer_free(idp);
513 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
515 SilcServer server = cmd->server;
516 char *nick = NULL, *server_name = NULL;
517 int count = 0, clients_count = 0;
518 SilcClientEntry *clients = NULL, entry;
519 SilcClientID **client_id = NULL;
520 unsigned int client_id_count = 0;
523 /* Protocol dictates that we must always send the received WHOIS request
524 to our router if we are normal server, so let's do it now unless we
525 are standalone. We will not send any replies to the client until we
526 have received reply from the router. */
527 if (server->server_type == SILC_SERVER &&
528 !cmd->pending && !server->standalone) {
530 unsigned short old_ident;
532 old_ident = silc_command_get_ident(cmd->payload);
533 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
534 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
536 /* Send WHOIS command to our router */
537 silc_server_packet_send(server, (SilcSocketConnection)
538 server->router->connection,
539 SILC_PACKET_COMMAND, cmd->packet->flags,
540 tmpbuf->data, tmpbuf->len, TRUE);
542 /* Reprocess this packet after received reply from router */
543 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
544 silc_command_get_ident(cmd->payload),
545 silc_server_command_whois, (void *)cmd);
548 silc_command_set_ident(cmd->payload, old_ident);
550 silc_buffer_free(tmpbuf);
555 /* We are ready to process the command request. Let's search for the
556 requested client and send reply to the requesting client. */
558 /* Parse the whois request */
559 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
560 &nick, &server_name, &count,
564 /* Get all clients matching that ID or nickname from local list */
565 if (client_id_count) {
566 /* Check all Client ID's received in the command packet */
567 for (i = 0; i < client_id_count; i++) {
568 entry = silc_idlist_find_client_by_id(server->local_list,
571 clients = silc_realloc(clients, sizeof(*clients) *
572 (clients_count + 1));
573 clients[clients_count++] = entry;
577 clients = silc_idlist_get_clients_by_nickname(server->local_list,
582 /* Check global list as well */
584 if (client_id_count) {
585 /* Check all Client ID's received in the command packet */
586 for (i = 0; i < client_id_count; i++) {
587 entry = silc_idlist_find_client_by_id(server->global_list,
590 clients = silc_realloc(clients, sizeof(*clients) *
591 (clients_count + 1));
592 clients[clients_count++] = entry;
596 clients = silc_idlist_get_clients_by_nickname(server->global_list,
603 /* Such client(s) really does not exist in the SILC network. */
604 if (!client_id_count) {
605 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
606 SILC_STATUS_ERR_NO_SUCH_NICK,
607 3, nick, strlen(nick));
609 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
610 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
611 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
612 2, idp->data, idp->len);
613 silc_buffer_free(idp);
618 /* Router always finds the client entry if it exists in the SILC network.
619 However, it might be incomplete entry and does not include all the
620 mandatory fields that WHOIS command reply requires. Check for these and
621 make query from the server who owns the client if some fields are
623 if (server->server_type == SILC_ROUTER &&
624 !silc_server_command_whois_check(cmd, clients, clients_count)) {
629 /* Send the command reply to the client */
630 silc_server_command_whois_send_reply(cmd, clients, clients_count);
633 if (client_id_count) {
634 for (i = 0; i < client_id_count; i++)
635 silc_free(client_id[i]);
636 silc_free(client_id);
643 silc_free(server_name);
649 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
651 SilcServer server = cmd->server;
652 char *nick = NULL, *server_name = NULL;
653 int count = 0, clients_count = 0;
654 SilcClientEntry *clients = NULL, entry;
655 SilcClientID **client_id = NULL;
656 unsigned int client_id_count = 0;
659 /* Parse the whois request */
660 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
661 &nick, &server_name, &count,
665 /* Process the command request. Let's search for the requested client and
666 send reply to the requesting server. */
668 if (client_id_count) {
669 /* Check all Client ID's received in the command packet */
670 for (i = 0; i < client_id_count; i++) {
671 entry = silc_idlist_find_client_by_id(server->local_list,
674 clients = silc_realloc(clients, sizeof(*clients) *
675 (clients_count + 1));
676 clients[clients_count++] = entry;
680 clients = silc_idlist_get_clients_by_nickname(server->local_list,
684 clients = silc_idlist_get_clients_by_hash(server->local_list,
685 nick, server->md5hash,
689 /* If we are router we will check our global list as well. */
690 if (!clients && server->server_type == SILC_ROUTER) {
691 if (client_id_count) {
692 /* Check all Client ID's received in the command packet */
693 for (i = 0; i < client_id_count; i++) {
694 entry = silc_idlist_find_client_by_id(server->global_list,
697 clients = silc_realloc(clients, sizeof(*clients) *
698 (clients_count + 1));
699 clients[clients_count++] = entry;
703 clients = silc_idlist_get_clients_by_nickname(server->global_list,
707 clients = silc_idlist_get_clients_by_hash(server->global_list,
708 nick, server->md5hash,
714 /* Such a client really does not exist in the SILC network. */
715 if (!client_id_count) {
716 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
717 SILC_STATUS_ERR_NO_SUCH_NICK,
718 3, nick, strlen(nick));
720 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
721 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
722 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
723 2, idp->data, idp->len);
724 silc_buffer_free(idp);
729 /* Router always finds the client entry if it exists in the SILC network.
730 However, it might be incomplete entry and does not include all the
731 mandatory fields that WHOIS command reply requires. Check for these and
732 make query from the server who owns the client if some fields are
734 if (server->server_type == SILC_ROUTER &&
735 !silc_server_command_whois_check(cmd, clients, clients_count)) {
740 /* Send the command reply to the client */
741 silc_server_command_whois_send_reply(cmd, clients, clients_count);
744 if (client_id_count) {
745 for (i = 0; i < client_id_count; i++)
746 silc_free(client_id[i]);
747 silc_free(client_id);
754 silc_free(server_name);
759 /* Server side of command WHOIS. Processes user's query and sends found
760 results as command replies back to the client. */
762 SILC_SERVER_CMD_FUNC(whois)
764 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
767 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3);
769 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
770 ret = silc_server_command_whois_from_client(cmd);
772 ret = silc_server_command_whois_from_server(cmd);
775 silc_server_command_free(cmd);
778 SILC_SERVER_CMD_FUNC(whowas)
782 /******************************************************************************
786 ******************************************************************************/
788 /* Checks that all mandatory fields are present. If not then send WHOIS
789 request to the server who owns the client. We use WHOIS because we want
790 to get as much information as possible at once. */
793 silc_server_command_identify_check(SilcServerCommandContext cmd,
794 SilcClientEntry *clients,
795 unsigned int clients_count)
797 SilcServer server = cmd->server;
799 SilcClientEntry entry;
801 for (i = 0; i < clients_count; i++) {
804 if (!entry->nickname) {
806 unsigned short old_ident;
808 old_ident = silc_command_get_ident(cmd->payload);
809 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
810 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
811 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
813 /* Send WHOIS request. We send WHOIS since we're doing the requesting
814 now anyway so make it a good one. */
815 silc_server_packet_send(server, entry->router->connection,
816 SILC_PACKET_COMMAND, cmd->packet->flags,
817 tmpbuf->data, tmpbuf->len, TRUE);
819 /* Reprocess this packet after received reply */
820 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
821 silc_command_get_ident(cmd->payload),
822 silc_server_command_identify, (void *)cmd);
825 /* Put old data back to the Command Payload we just changed */
826 silc_command_set_ident(cmd->payload, old_ident);
827 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
829 silc_buffer_free(tmpbuf);
838 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
839 SilcClientEntry *clients,
840 unsigned int clients_count)
842 SilcServer server = cmd->server;
844 int i, count = 0, len;
845 SilcBuffer packet, idp;
846 SilcClientEntry entry;
847 SilcCommandStatus status;
848 unsigned short ident = silc_command_get_ident(cmd->payload);
850 status = SILC_STATUS_OK;
851 if (clients_count > 1)
852 status = SILC_STATUS_LIST_START;
854 for (i = 0; i < clients_count; i++) {
857 if (count && i - 1 == count)
860 if (clients_count > 2)
861 status = SILC_STATUS_LIST_ITEM;
863 if (clients_count > 1 && i == clients_count - 1)
864 status = SILC_STATUS_LIST_END;
866 /* Send IDENTIFY reply */
867 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
868 tmp = silc_argument_get_first_arg(cmd->args, NULL);
872 char nh[256], uh[256];
873 SilcSocketConnection hsock;
875 memset(uh, 0, sizeof(uh));
876 memset(nh, 0, sizeof(nh));
878 strncat(nh, entry->nickname, strlen(entry->nickname));
879 if (!strchr(entry->nickname, '@')) {
881 len = entry->router ? strlen(entry->router->server_name) :
882 strlen(server->server_name);
883 strncat(nh, entry->router ? entry->router->server_name :
884 server->server_name, len);
887 if (!entry->username) {
888 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
889 SILC_STATUS_OK, ident, 2,
890 2, idp->data, idp->len,
893 strncat(uh, entry->username, strlen(entry->username));
894 if (!strchr(entry->username, '@')) {
896 hsock = (SilcSocketConnection)entry->connection;
897 len = strlen(hsock->hostname);
898 strncat(uh, hsock->hostname, len);
901 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
902 SILC_STATUS_OK, ident, 3,
903 2, idp->data, idp->len,
908 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
909 0, packet->data, packet->len, FALSE);
911 silc_buffer_free(packet);
912 silc_buffer_free(idp);
918 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
920 SilcServer server = cmd->server;
921 char *nick = NULL, *server_name = NULL;
922 int count = 0, clients_count;
923 SilcClientEntry *clients = NULL, entry;
924 SilcClientID **client_id = NULL;
925 unsigned int client_id_count = 0;
928 /* Protocol dictates that we must always send the received IDENTIFY request
929 to our router if we are normal server, so let's do it now unless we
930 are standalone. We will not send any replies to the client until we
931 have received reply from the router. */
932 if (server->server_type == SILC_SERVER &&
933 !cmd->pending && !server->standalone) {
935 unsigned short old_ident;
937 old_ident = silc_command_get_ident(cmd->payload);
938 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
939 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
941 /* Send IDENTIFY command to our router */
942 silc_server_packet_send(server, (SilcSocketConnection)
943 server->router->connection,
944 SILC_PACKET_COMMAND, cmd->packet->flags,
945 tmpbuf->data, tmpbuf->len, TRUE);
947 /* Reprocess this packet after received reply from router */
948 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
949 silc_command_get_ident(cmd->payload),
950 silc_server_command_identify, (void *)cmd);
953 silc_command_set_ident(cmd->payload, old_ident);
955 silc_buffer_free(tmpbuf);
960 /* We are ready to process the command request. Let's search for the
961 requested client and send reply to the requesting client. */
963 /* Parse the IDENTIFY request */
964 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
965 &nick, &server_name, &count,
966 SILC_COMMAND_IDENTIFY))
969 /* Get all clients matching that ID or nickname from local list */
970 if (client_id_count) {
971 /* Check all Client ID's received in the command packet */
972 for (i = 0; i < client_id_count; i++) {
973 entry = silc_idlist_find_client_by_id(server->local_list,
976 clients = silc_realloc(clients, sizeof(*clients) *
977 (clients_count + 1));
978 clients[clients_count++] = entry;
982 clients = silc_idlist_get_clients_by_nickname(server->local_list,
987 /* Check global list as well */
989 if (client_id_count) {
990 /* Check all Client ID's received in the command packet */
991 for (i = 0; i < client_id_count; i++) {
992 entry = silc_idlist_find_client_by_id(server->global_list,
995 clients = silc_realloc(clients, sizeof(*clients) *
996 (clients_count + 1));
997 clients[clients_count++] = entry;
1001 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1008 /* Such a client really does not exist in the SILC network. */
1009 if (!client_id_count) {
1010 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1011 SILC_STATUS_ERR_NO_SUCH_NICK,
1012 3, nick, strlen(nick));
1014 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1015 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1016 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1017 2, idp->data, idp->len);
1018 silc_buffer_free(idp);
1023 /* Check that all mandatory fields are present and request those data
1024 from the server who owns the client if necessary. */
1025 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1026 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1031 /* Send the command reply to the client */
1032 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1035 if (client_id_count) {
1036 for (i = 0; i < client_id_count; i++)
1037 silc_free(client_id[i]);
1038 silc_free(client_id);
1045 silc_free(server_name);
1051 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1053 SilcServer server = cmd->server;
1054 char *nick = NULL, *server_name = NULL;
1055 int count = 0, clients_count;
1056 SilcClientEntry *clients = NULL, entry;
1057 SilcClientID **client_id = NULL;
1058 unsigned int client_id_count = 0;
1061 /* Parse the IDENTIFY request */
1062 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1063 &nick, &server_name, &count,
1064 SILC_COMMAND_IDENTIFY))
1067 /* Process the command request. Let's search for the requested client and
1068 send reply to the requesting server. */
1070 if (client_id_count) {
1071 /* Check all Client ID's received in the command packet */
1072 for (i = 0; i < client_id_count; i++) {
1073 entry = silc_idlist_find_client_by_id(server->local_list,
1074 client_id[i], NULL);
1076 clients = silc_realloc(clients, sizeof(*clients) *
1077 (clients_count + 1));
1078 clients[clients_count++] = entry;
1082 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1086 clients = silc_idlist_get_clients_by_hash(server->local_list,
1087 nick, server->md5hash,
1091 /* If we are router we will check our global list as well. */
1092 if (!clients && server->server_type == SILC_ROUTER) {
1093 if (client_id_count) {
1094 /* Check all Client ID's received in the command packet */
1095 for (i = 0; i < client_id_count; i++) {
1096 entry = silc_idlist_find_client_by_id(server->global_list,
1097 client_id[i], NULL);
1099 clients = silc_realloc(clients, sizeof(*clients) *
1100 (clients_count + 1));
1101 clients[clients_count++] = entry;
1105 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1109 clients = silc_idlist_get_clients_by_hash(server->global_list,
1110 nick, server->md5hash,
1116 /* Such a client really does not exist in the SILC network. */
1117 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1118 SILC_STATUS_ERR_NO_SUCH_NICK,
1119 3, nick, strlen(nick));
1123 /* Check that all mandatory fields are present and request those data
1124 from the server who owns the client if necessary. */
1125 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1126 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1131 /* Send the command reply */
1132 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1135 if (client_id_count) {
1136 for (i = 0; i < client_id_count; i++)
1137 silc_free(client_id[i]);
1138 silc_free(client_id);
1145 silc_free(server_name);
1150 SILC_SERVER_CMD_FUNC(identify)
1152 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1155 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3);
1157 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1158 ret = silc_server_command_identify_from_client(cmd);
1160 ret = silc_server_command_identify_from_server(cmd);
1163 silc_server_command_free(cmd);
1166 /* Checks string for bad characters and returns TRUE if they are found. */
1168 static int silc_server_command_bad_chars(char *nick)
1170 if (strchr(nick, '\\')) return TRUE;
1171 if (strchr(nick, '\"')) return TRUE;
1172 if (strchr(nick, '´')) return TRUE;
1173 if (strchr(nick, '`')) return TRUE;
1174 if (strchr(nick, '\'')) return TRUE;
1175 if (strchr(nick, '*')) return TRUE;
1176 if (strchr(nick, '/')) return TRUE;
1177 if (strchr(nick, '@')) return TRUE;
1182 /* Server side of command NICK. Sets nickname for user. Setting
1183 nickname causes generation of a new client ID for the client. The
1184 new client ID is sent to the client after changing the nickname. */
1186 SILC_SERVER_CMD_FUNC(nick)
1188 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1189 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1190 SilcServer server = cmd->server;
1191 SilcBuffer packet, nidp, oidp;
1192 SilcClientID *new_id;
1195 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1197 /* Check nickname */
1198 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1199 if (silc_server_command_bad_chars(nick) == TRUE) {
1200 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1201 SILC_STATUS_ERR_BAD_NICKNAME);
1205 /* Create new Client ID */
1206 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1207 cmd->server->md5hash, nick,
1210 /* Send notify about nickname change to our router. We send the new
1211 ID and ask to replace it with the old one. If we are router the
1212 packet is broadcasted. */
1213 if (!cmd->server->standalone)
1214 silc_server_send_replace_id(server, server->router->connection,
1215 server->server_type == SILC_SERVER ?
1216 FALSE : TRUE, client->id,
1217 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1218 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1220 /* Remove old cache entry */
1221 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1224 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1228 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1229 silc_free(client->id);
1232 /* Save the nickname as this client is our local client */
1233 if (client->nickname)
1234 silc_free(client->nickname);
1236 client->nickname = strdup(nick);
1237 client->id = new_id;
1239 /* Update client cache */
1240 silc_idcache_add(server->local_list->clients, client->nickname,
1241 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1243 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1245 /* Send NICK_CHANGE notify */
1246 silc_server_send_notify_on_channels(server, client,
1247 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1248 oidp->data, oidp->len,
1249 nidp->data, nidp->len);
1251 /* Send the new Client ID as reply command back to client */
1252 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1253 SILC_STATUS_OK, 0, 1,
1254 2, nidp->data, nidp->len);
1255 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1256 0, packet->data, packet->len, FALSE);
1258 silc_buffer_free(packet);
1259 silc_buffer_free(nidp);
1260 silc_buffer_free(oidp);
1263 silc_server_command_free(cmd);
1266 SILC_SERVER_CMD_FUNC(list)
1270 /* Server side of TOPIC command. Sets topic for channel and/or returns
1271 current topic to client. */
1273 SILC_SERVER_CMD_FUNC(topic)
1275 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1276 SilcServer server = cmd->server;
1277 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1278 SilcChannelID *channel_id;
1279 SilcChannelEntry channel;
1280 SilcChannelClientEntry chl;
1281 SilcBuffer packet, idp;
1283 unsigned int argc, tmp_len;
1285 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1287 argc = silc_argument_get_arg_num(cmd->args);
1289 /* Get Channel ID */
1290 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1293 SILC_STATUS_ERR_NO_CHANNEL_ID);
1296 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1298 /* Check whether the channel exists */
1299 channel = silc_idlist_find_channel_by_id(server->local_list,
1302 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1303 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1309 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1312 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1316 if (strlen(tmp) > 256) {
1317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1318 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1322 /* See whether has rights to change topic */
1323 silc_list_start(channel->user_list);
1324 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1325 if (chl->client == client) {
1326 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1328 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1336 /* Set the topic for channel */
1338 silc_free(channel->topic);
1339 channel->topic = strdup(tmp);
1341 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1343 /* Send notify about topic change to all clients on the channel */
1344 silc_server_send_notify_to_channel(server, channel, TRUE,
1345 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1346 idp->data, idp->len,
1347 channel->topic, strlen(channel->topic));
1348 silc_buffer_free(idp);
1351 /* Send the topic to client as reply packet */
1352 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1354 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1355 SILC_STATUS_OK, 0, 2,
1356 2, idp->data, idp->len,
1358 strlen(channel->topic));
1360 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1361 SILC_STATUS_OK, 0, 1,
1362 2, idp->data, idp->len);
1363 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1364 0, packet->data, packet->len, FALSE);
1366 silc_buffer_free(packet);
1367 silc_buffer_free(idp);
1368 silc_free(channel_id);
1371 silc_server_command_free(cmd);
1374 /* Server side of INVITE command. Invites some client to join some channel. */
1376 SILC_SERVER_CMD_FUNC(invite)
1378 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1379 SilcServer server = cmd->server;
1380 SilcSocketConnection sock = cmd->sock, dest_sock;
1381 SilcClientEntry sender, dest;
1382 SilcClientID *dest_id;
1383 SilcChannelEntry channel;
1384 SilcChannelID *channel_id;
1389 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1391 /* Get destination ID */
1392 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1394 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1395 SILC_STATUS_ERR_NO_CLIENT_ID);
1398 dest_id = silc_id_payload_parse_id(tmp, len);
1400 /* Get Channel ID */
1401 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1404 SILC_STATUS_ERR_NO_CHANNEL_ID);
1407 channel_id = silc_id_payload_parse_id(tmp, len);
1409 /* Check whether the channel exists */
1410 channel = silc_idlist_find_channel_by_id(server->local_list,
1413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1414 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1418 /* Check whether the sender of this command is on the channel. */
1419 sender = (SilcClientEntry)sock->user_data;
1420 if (!silc_server_client_on_channel(sender, channel)) {
1421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1422 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1426 /* Check whether the channel is invite-only channel. If yes then the
1427 sender of this command must be at least channel operator. */
1428 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1429 SilcChannelClientEntry chl;
1431 silc_list_start(channel->user_list);
1432 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1433 if (chl->client == sender) {
1434 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1436 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1443 /* Find the connection data for the destination. If it is local we will
1444 send it directly otherwise we will send it to router for routing. */
1445 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1447 dest_sock = (SilcSocketConnection)dest->connection;
1449 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1451 /* Check whether the requested client is already on the channel. */
1452 /* XXX if we are normal server we don't know about global clients on
1453 the channel thus we must request it (USERS command), check from
1454 local cache as well. */
1455 if (silc_server_client_on_channel(dest, channel)) {
1456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1457 SILC_STATUS_ERR_USER_ON_CHANNEL);
1461 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1463 /* Send notify to the client that is invited to the channel */
1464 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1465 SILC_NOTIFY_TYPE_INVITE, 2,
1466 sidp->data, sidp->len, tmp, len);
1468 /* Send command reply */
1469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1472 silc_buffer_free(sidp);
1475 silc_server_command_free(cmd);
1478 /* Quits connection to client. This gets called if client won't
1479 close the connection even when it has issued QUIT command. */
1481 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1483 SilcServer server = (SilcServer)context;
1484 SilcSocketConnection sock = server->sockets[fd];
1486 /* Free all client specific data, such as client entry and entires
1487 on channels this client may be on. */
1488 silc_server_free_sock_user_data(server, sock);
1490 /* Close the connection on our side */
1491 silc_server_close_connection(server, sock);
1494 /* Quits SILC session. This is the normal way to disconnect client. */
1496 SILC_SERVER_CMD_FUNC(quit)
1498 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1499 SilcServer server = cmd->server;
1500 SilcSocketConnection sock = cmd->sock;
1502 SILC_LOG_DEBUG(("Start"));
1504 /* We quit the connection with little timeout */
1505 silc_task_register(server->timeout_queue, sock->sock,
1506 silc_server_command_quit_cb, server,
1507 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1509 silc_server_command_free(cmd);
1512 SILC_SERVER_CMD_FUNC(kill)
1516 /* Server side of command INFO. This sends information about us to
1517 the client. If client requested specific server we will send the
1518 command to that server. */
1520 SILC_SERVER_CMD_FUNC(info)
1522 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1523 SilcServer server = cmd->server;
1524 SilcBuffer packet, idp;
1525 char info_string[256], *dest_server;
1527 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1529 /* Get server name */
1530 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1533 SILC_STATUS_ERR_NO_SUCH_SERVER);
1537 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1538 /* Send our reply */
1539 memset(info_string, 0, sizeof(info_string));
1540 snprintf(info_string, sizeof(info_string),
1541 "location: %s server: %s admin: %s <%s>",
1542 server->config->admin_info->location,
1543 server->config->admin_info->server_type,
1544 server->config->admin_info->admin_name,
1545 server->config->admin_info->admin_email);
1547 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1549 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1550 SILC_STATUS_OK, 0, 2,
1551 2, idp->data, idp->len,
1553 strlen(info_string));
1554 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1555 packet->data, packet->len, FALSE);
1557 silc_buffer_free(packet);
1558 silc_buffer_free(idp);
1560 /* Send this command to the requested server */
1562 if (server->server_type == SILC_SERVER && !server->standalone) {
1566 if (server->server_type == SILC_ROUTER) {
1572 silc_server_command_free(cmd);
1575 SILC_SERVER_CMD_FUNC(connect)
1579 /* Server side of command PING. This just replies to the ping. */
1581 SILC_SERVER_CMD_FUNC(ping)
1583 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1584 SilcServer server = cmd->server;
1589 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1592 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1594 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1595 SILC_STATUS_ERR_NO_SERVER_ID);
1598 id = silc_id_str2id(tmp, SILC_ID_SERVER);
1602 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1603 /* Send our reply */
1604 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1608 SILC_STATUS_ERR_NO_SUCH_SERVER);
1615 silc_server_command_free(cmd);
1618 SILC_SERVER_CMD_FUNC(oper)
1627 SilcChannelEntry channel;
1629 SilcClientEntry client;
1630 } JoinInternalContext;
1632 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1634 JoinInternalContext *ctx = (JoinInternalContext *)context;
1636 if (ctx->channel->key && ctx->channel->key_len) {
1639 clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1641 silc_server_send_notify_to_channel(ctx->server, ctx->channel, FALSE,
1642 SILC_NOTIFY_TYPE_JOIN, 1,
1643 clidp->data, clidp->len);
1645 /* Send NEW_CHANNEL_USER packet to primary route */
1646 silc_server_send_new_channel_user(server, server->router->connection,
1647 server->server_type == SILC_SERVER ?
1649 channel->id, SILC_ID_CHANNEL_LEN,
1650 client->id, SILC_ID_CLIENT_LEN);
1653 /* Send USERS command reply to the joined channel so the user sees who
1654 is currently on the channel. */
1655 silc_server_command_send_users(ctx->server, ctx->client->connection,
1658 silc_buffer_free(clidp);
1661 silc_task_register(ctx->server->timeout_queue, fd,
1662 silc_server_command_join_notify, context,
1663 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1667 /* Assembles USERS command and executes it. This is called when client
1668 joins to a channel and we wan't to send USERS command reply to the
1671 void silc_server_command_send_users(SilcServer server,
1672 SilcSocketConnection sock,
1673 SilcChannelEntry channel)
1675 SilcServerCommandContext cmd;
1676 SilcBuffer buffer, idp;
1677 SilcPacketContext *packet = silc_packet_context_alloc();
1679 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1680 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1681 1, idp->data, idp->len);
1683 packet->buffer = silc_buffer_copy(buffer);
1684 packet->sock = sock;
1685 packet->type = SILC_PACKET_COMMAND;
1687 cmd = silc_calloc(1, sizeof(*cmd));
1688 cmd->payload = silc_command_payload_parse(buffer);
1689 cmd->args = silc_command_get_args(cmd->payload);
1690 cmd->server = server;
1692 cmd->packet = silc_packet_context_dup(packet);
1693 cmd->pending = FALSE;
1695 silc_server_command_users((void *)cmd);
1699 silc_packet_context_free(packet);
1702 /* Internal routine that is called after router has replied to server's
1703 JOIN command it forwarded to the router. The route has joined and possibly
1704 creaetd the channel. This function adds the client to the channel's user
1707 SILC_SERVER_CMD_FUNC(add_to_channel)
1709 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1710 SilcServer server = cmd->server;
1711 SilcClientEntry client;
1712 SilcChannelEntry channel;
1713 SilcChannelClientEntry chl;
1716 /* Get channel name */
1717 channel_name = silc_argument_get_arg_type(cmd->args, 1, NULL);
1719 /* Get client entry */
1720 client = (SilcClientEntry)cmd->sock->user_data;
1722 /* Get channel entry */
1723 channel = silc_idlist_find_channel_by_name(server->local_list,
1724 channel_name, NULL);
1726 /* Join the client to the channel by adding it to channel's user list.
1727 Add also the channel to client entry's channels list for fast cross-
1729 chl = silc_calloc(1, sizeof(*chl));
1730 //chl->mode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
1731 chl->client = client;
1732 chl->channel = channel;
1733 silc_list_add(channel->user_list, chl);
1734 silc_list_add(client->channels, chl);
1737 silc_server_command_free(cmd);
1740 /* Internal routine to join channel. The channel sent to this function
1741 has been either created or resolved from ID lists. This joins the sent
1742 client to the channel. */
1744 static void silc_server_command_join_channel(SilcServer server,
1745 SilcServerCommandContext cmd,
1746 SilcChannelEntry channel,
1747 SilcClientID *client_id,
1751 SilcSocketConnection sock = cmd->sock;
1753 unsigned int tmp_len;
1754 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1755 SilcClientEntry client;
1756 SilcChannelClientEntry chl;
1757 SilcBuffer reply, chidp, clidp, keyp;
1758 unsigned short ident = silc_command_get_ident(cmd->payload);
1760 SILC_LOG_DEBUG(("Start"));
1765 /* Get passphrase */
1766 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1768 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1769 memcpy(passphrase, tmp, tmp_len);
1773 * Check channel modes
1776 /* Check invite list if channel is invite-only channel */
1777 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1778 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1779 /* Invite list is specified. Check whether client is invited in the
1780 list. If not, then check whether it has been invited otherwise. */
1783 /* XXX client must be invited to be able to join the channel */
1787 /* Check ban list if set */
1788 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1792 /* Check the channel passphrase if set. */
1793 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1794 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1795 strlen(channel->mode_data.passphrase))) {
1796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1797 SILC_STATUS_ERR_BAD_PASSWORD);
1802 /* Check user count limit if set. */
1803 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1804 if (silc_list_count(channel->user_list) + 1 >
1805 channel->mode_data.user_limit) {
1806 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1807 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1813 * Client is allowed to join to the channel. Make it happen.
1816 /* Get the client entry */
1817 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1818 client = (SilcClientEntry)sock->user_data;
1820 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1823 /* XXX actually this is useless since router finds always cell's
1824 local clients from its local lists. */
1825 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1832 /* Check whether the client already is on the channel */
1833 if (silc_server_client_on_channel(client, channel)) {
1834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1835 SILC_STATUS_ERR_USER_ON_CHANNEL);
1839 /* Generate new channel key as protocol dictates */
1840 if (!created || !channel->channel_key)
1841 silc_server_create_channel_key(server, channel, 0);
1843 /* Send the channel key. This is broadcasted to the channel but is not
1844 sent to the client who is joining to the channel. */
1845 silc_server_send_channel_key(server, channel,
1846 server->server_type == SILC_ROUTER ?
1847 FALSE : server->standalone);
1849 /* Join the client to the channel by adding it to channel's user list.
1850 Add also the channel to client entry's channels list for fast cross-
1852 chl = silc_calloc(1, sizeof(*chl));
1854 chl->client = client;
1855 chl->channel = channel;
1856 silc_list_add(channel->user_list, chl);
1857 silc_list_add(client->channels, chl);
1859 /* Encode Client ID Payload of the original client who wants to join */
1860 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1862 /* Encode command reply packet */
1863 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1864 SILC_PUT32_MSB(channel->mode, mode);
1865 SILC_PUT32_MSB(created, tmp2);
1866 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1867 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1868 SILC_ID_CHANNEL_LEN,
1869 channel->channel_key->cipher->name,
1870 channel->key_len / 8, channel->key);
1872 if (!channel->topic) {
1874 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1875 SILC_STATUS_OK, ident, 5,
1876 2, channel->channel_name,
1877 strlen(channel->channel_name),
1878 3, chidp->data, chidp->len,
1881 6, keyp->data, keyp->len);
1884 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1885 SILC_STATUS_OK, ident, 6,
1886 2, channel->channel_name,
1887 strlen(channel->channel_name),
1888 3, chidp->data, chidp->len,
1891 6, keyp->data, keyp->len,
1893 strlen(channel->topic));
1896 /* Send command reply */
1897 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1898 reply->data, reply->len, FALSE);
1901 /* Send JOIN notify to locally connected clients on the channel */
1902 silc_server_send_notify_to_channel(server, channel, FALSE,
1903 SILC_NOTIFY_TYPE_JOIN, 1,
1904 clidp->data, clidp->len);
1906 /* Send NEW_CHANNEL_USER packet to our primary router */
1907 if (!cmd->pending && !server->standalone)
1908 silc_server_send_new_channel_user(server, server->router->connection,
1909 server->server_type == SILC_SERVER ?
1911 channel->id, SILC_ID_CHANNEL_LEN,
1912 client->id, SILC_ID_CLIENT_LEN);
1914 /* Send USERS command reply to the joined channel so the user sees who
1915 is currently on the channel. */
1916 silc_server_command_send_users(server, sock, channel);
1922 * Kuinka USERS komento händlätään serverissä kun router lähettää sen
1923 serverille joka on lähettäny sille clientin puolesta JOIN komennon?
1925 R: Serverin pitää ymmärtää USERS comman replyjä.
1929 silc_buffer_free(reply);
1930 silc_buffer_free(clidp);
1931 silc_buffer_free(chidp);
1932 silc_buffer_free(keyp);
1936 silc_free(passphrase);
1939 /* Server side of command JOIN. Joins client into requested channel. If
1940 the channel does not exist it will be created. */
1942 SILC_SERVER_CMD_FUNC(join)
1944 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1945 SilcServer server = cmd->server;
1947 char *tmp, *channel_name = NULL, *cipher = NULL;
1948 SilcChannelEntry channel;
1949 unsigned int umode = 0;
1950 int created = FALSE;
1951 SilcClientID *client_id;
1953 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1955 /* Get channel name */
1956 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1958 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1959 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1964 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1965 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1966 SILC_STATUS_ERR_BAD_CHANNEL);
1967 silc_free(channel_name);
1971 /* Get Client ID of the client who is joining to the channel */
1972 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1975 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1978 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1980 /* Get cipher name */
1981 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
1983 /* See if the channel exists */
1984 channel = silc_idlist_find_channel_by_name(server->local_list,
1985 channel_name, NULL);
1987 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1988 /* If this is coming from client the Client ID in the command packet must
1989 be same as the client's ID. */
1990 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1991 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
1992 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
1993 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1994 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2000 /* Channel not found */
2002 /* If we are standalone server we don't have a router, we just create
2003 the channel by ourselves. */
2004 if (server->standalone) {
2005 channel = silc_server_create_new_channel(server, server->id, cipher,
2007 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2012 /* The channel does not exist on our server. If we are normal server
2013 we will send JOIN command to our router which will handle the
2014 joining procedure (either creates the channel if it doesn't exist
2015 or joins the client to it). */
2016 if (server->server_type == SILC_SERVER) {
2018 unsigned short old_ident;
2020 old_ident = silc_command_get_ident(cmd->payload);
2021 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2022 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2024 /* Send JOIN command to our router */
2025 silc_server_packet_send(server, (SilcSocketConnection)
2026 server->router->connection,
2027 SILC_PACKET_COMMAND, cmd->packet->flags,
2028 tmpbuf->data, tmpbuf->len, TRUE);
2030 /* Reprocess this packet after received reply from router */
2031 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2032 silc_command_get_ident(cmd->payload),
2033 silc_server_command_join, context);
2034 cmd->pending = TRUE;
2038 /* We are router and the channel does not seem exist so we will check
2039 our global list as well for the channel. */
2040 channel = silc_idlist_find_channel_by_name(server->global_list,
2041 channel_name, NULL);
2043 /* Channel really does not exist, create it */
2044 channel = silc_server_create_new_channel(server, server->id, cipher,
2046 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2053 /* Channel not found */
2055 /* If the command came from router and/or we are normal server then
2056 something went wrong with the joining as the channel was not found.
2057 We can't do anything else but ignore this. */
2058 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2059 server->server_type == SILC_SERVER)
2062 /* We are router and the channel does not seem exist so we will check
2063 our global list as well for the channel. */
2064 channel = silc_idlist_find_channel_by_name(server->global_list,
2065 channel_name, NULL);
2067 /* Channel really does not exist, create it */
2068 channel = silc_server_create_new_channel(server, server->id, cipher,
2070 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2076 /* If the channel does not have global users and is also empty it means the
2077 channel was created globally (by our router) and the client will be the
2078 channel founder and operator. */
2079 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2080 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2081 created = TRUE; /* Created globally by our router */
2084 /* Join to the channel */
2085 silc_server_command_join_channel(server, cmd, channel, client_id,
2088 silc_free(client_id);
2091 silc_server_command_free(cmd);
2094 /* Server side of command MOTD. Sends server's current "message of the
2095 day" to the client. */
2097 SILC_SERVER_CMD_FUNC(motd)
2099 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2100 SilcServer server = cmd->server;
2104 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2106 /* XXX show currently only our motd */
2108 if (server->config && server->config->motd &&
2109 server->config->motd->motd_file) {
2112 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2117 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2123 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2128 silc_server_command_free(cmd);
2131 SILC_SERVER_CMD_FUNC(umode)
2135 /* Checks that client has rights to add or remove channel modes. If any
2136 of the checks fails FALSE is returned. */
2138 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2139 SilcChannelClientEntry client,
2142 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2143 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2145 /* Check whether has rights to change anything */
2146 if (!is_op && !is_fo)
2149 /* Check whether has rights to change everything */
2153 /* We know that client is channel operator, check that they are not
2154 changing anything that requires channel founder rights. Rest of the
2155 modes are available automatically for channel operator. */
2157 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2158 if (is_op && !is_fo)
2161 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2162 if (is_op && !is_fo)
2167 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2168 if (is_op && !is_fo)
2171 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2172 if (is_op && !is_fo)
2177 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2178 if (is_op && !is_fo)
2181 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2182 if (is_op && !is_fo)
2190 /* Server side command of CMODE. Changes channel mode */
2192 SILC_SERVER_CMD_FUNC(cmode)
2194 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2195 SilcServer server = cmd->server;
2196 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2197 SilcChannelID *channel_id;
2198 SilcChannelEntry channel;
2199 SilcChannelClientEntry chl;
2200 SilcBuffer packet, cidp;
2201 unsigned char *tmp, *tmp_id, *tmp_mask;
2202 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2204 SILC_LOG_DEBUG(("Start"));
2206 argc = silc_argument_get_arg_num(cmd->args);
2208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2209 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2214 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2218 /* Get Channel ID */
2219 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2221 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2222 SILC_STATUS_ERR_NO_CHANNEL_ID);
2225 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2227 /* Get the channel mode mask */
2228 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2231 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2234 SILC_GET32_MSB(mode_mask, tmp_mask);
2236 /* Get channel entry */
2237 channel = silc_idlist_find_channel_by_id(server->local_list,
2240 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2241 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2245 /* Check whether this client is on the channel */
2246 if (!silc_server_client_on_channel(client, channel)) {
2247 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2248 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2252 /* Get entry to the channel user list */
2253 silc_list_start(channel->user_list);
2254 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2255 if (chl->client == client)
2258 /* Check that client has rights to change any requested channel modes */
2259 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2260 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2261 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2266 * Check the modes. Modes that requires nothing special operation are
2270 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2271 /* Channel uses private keys to protect traffic. Client(s) has set the
2272 key locally they want to use, server does not know that key. */
2273 /* Nothing interesting to do here now */
2275 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2276 /* The mode is removed and we need to generate and distribute
2277 new channel key. Clients are not using private channel keys
2278 anymore after this. */
2280 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2283 /* Re-generate channel key */
2284 silc_server_create_channel_key(server, channel, 0);
2286 /* Encode channel key payload to be distributed on the channel */
2288 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2289 strlen(channel->channel_key->
2291 channel->channel_key->cipher->name,
2292 channel->key_len / 8, channel->key);
2294 /* If we are normal server then we will send it to our router. If we
2295 are router we will send it to all local servers that has clients on
2297 if (server->server_type == SILC_SERVER) {
2298 if (!server->standalone)
2299 silc_server_packet_send(server,
2300 cmd->server->router->connection,
2301 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2307 /* Send to locally connected clients on the channel */
2308 silc_server_packet_send_local_channel(server, channel,
2309 SILC_PACKET_CHANNEL_KEY, 0,
2310 packet->data, packet->len, FALSE);
2311 silc_buffer_free(packet);
2315 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2316 /* User limit is set on channel */
2317 unsigned int user_limit;
2319 /* Get user limit */
2320 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2322 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2323 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2324 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2328 SILC_GET32_MSB(user_limit, tmp);
2329 channel->mode_data.user_limit = user_limit;
2332 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2333 /* User limit mode is unset. Remove user limit */
2334 channel->mode_data.user_limit = 0;
2337 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2338 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2339 /* Passphrase has been set to channel */
2341 /* Get the passphrase */
2342 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2345 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2349 /* Save the passphrase */
2350 channel->mode_data.passphrase = strdup(tmp);
2353 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2354 /* Passphrase mode is unset. remove the passphrase */
2355 if (channel->mode_data.passphrase) {
2356 silc_free(channel->mode_data.passphrase);
2357 channel->mode_data.passphrase = NULL;
2362 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2363 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2364 /* Ban list is specified for channel */
2367 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2369 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2370 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2374 /* XXX check that channel founder is not banned */
2376 /* Save the ban list */
2377 channel->mode_data.ban_list = strdup(tmp);
2380 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2381 /* Ban mode is unset. Remove the entire ban list */
2382 if (channel->mode_data.ban_list) {
2383 silc_free(channel->mode_data.ban_list);
2384 channel->mode_data.ban_list = NULL;
2389 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2390 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2391 /* Invite list is specified for channel */
2393 /* Get invite list */
2394 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2396 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2397 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2401 /* Save the invite linst */
2402 channel->mode_data.invite_list = strdup(tmp);
2405 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2406 /* Invite list mode is unset. Remove the entire invite list */
2407 if (channel->mode_data.invite_list) {
2408 silc_free(channel->mode_data.invite_list);
2409 channel->mode_data.invite_list = NULL;
2414 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2415 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2416 /* Cipher to use protect the traffic */
2417 unsigned int key_len = 128;
2421 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2424 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2428 cp = strchr(tmp, ':');
2434 /* XXX Duplicated code, make own function for this!! */
2436 /* Delete old cipher and allocate the new one */
2437 silc_cipher_free(channel->channel_key);
2438 silc_cipher_alloc(tmp, &channel->channel_key);
2444 /* Re-generate channel key */
2445 silc_server_create_channel_key(server, channel, key_len);
2447 /* Encode channel key payload to be distributed on the channel */
2449 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2450 strlen(channel->channel_key->
2452 channel->channel_key->cipher->name,
2453 channel->key_len / 8, channel->key);
2455 /* If we are normal server then we will send it to our router. If we
2456 are router we will send it to all local servers that has clients on
2458 if (server->server_type == SILC_SERVER) {
2459 if (!server->standalone)
2460 silc_server_packet_send(server,
2461 cmd->server->router->connection,
2462 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2468 /* Send to locally connected clients on the channel */
2469 silc_server_packet_send_local_channel(server, channel,
2470 SILC_PACKET_CHANNEL_KEY, 0,
2471 packet->data, packet->len, FALSE);
2472 silc_buffer_free(packet);
2475 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2476 /* Cipher mode is unset. Remove the cipher and revert back to
2479 if (channel->mode_data.cipher) {
2480 silc_free(channel->mode_data.cipher);
2481 channel->mode_data.cipher = NULL;
2482 channel->mode_data.key_len = 0;
2485 /* Generate new cipher and key for the channel */
2487 /* XXX Duplicated code, make own function for this!! */
2489 /* Delete old cipher and allocate default one */
2490 silc_cipher_free(channel->channel_key);
2491 if (!channel->cipher)
2492 silc_cipher_alloc("twofish", &channel->channel_key);
2494 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2496 /* Re-generate channel key */
2497 silc_server_create_channel_key(server, channel, 0);
2499 /* Encode channel key payload to be distributed on the channel */
2501 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2502 strlen(channel->channel_key->
2504 channel->channel_key->cipher->name,
2505 channel->key_len / 8, channel->key);
2507 /* If we are normal server then we will send it to our router. If we
2508 are router we will send it to all local servers that has clients on
2510 if (server->server_type == SILC_SERVER) {
2511 if (!server->standalone)
2512 silc_server_packet_send(server,
2513 cmd->server->router->connection,
2514 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2520 /* Send to locally connected clients on the channel */
2521 silc_server_packet_send_local_channel(server, channel,
2522 SILC_PACKET_CHANNEL_KEY, 0,
2523 packet->data, packet->len, FALSE);
2524 silc_buffer_free(packet);
2528 /* Finally, set the mode */
2529 channel->mode = mode_mask;
2531 /* Send CMODE_CHANGE notify */
2532 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2533 silc_server_send_notify_to_channel(server, channel, TRUE,
2534 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2535 cidp->data, cidp->len,
2539 /* Send command reply to sender */
2540 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2541 SILC_STATUS_OK, 0, 1,
2543 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2544 packet->data, packet->len, FALSE);
2546 silc_buffer_free(packet);
2547 silc_free(channel_id);
2550 silc_server_command_free(cmd);
2553 /* Server side of CUMODE command. Changes client's mode on a channel. */
2555 SILC_SERVER_CMD_FUNC(cumode)
2557 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2558 SilcServer server = cmd->server;
2559 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2560 SilcChannelID *channel_id;
2561 SilcClientID *client_id;
2562 SilcChannelEntry channel;
2563 SilcClientEntry target_client;
2564 SilcChannelClientEntry chl;
2565 SilcBuffer packet, idp;
2566 unsigned char *tmp_id, *tmp_mask;
2567 unsigned int target_mask, sender_mask, tmp_len;
2570 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2572 /* Get Channel ID */
2573 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2575 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2576 SILC_STATUS_ERR_NO_CHANNEL_ID);
2579 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2581 /* Get channel entry */
2582 channel = silc_idlist_find_channel_by_id(server->local_list,
2585 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2586 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2590 /* Check whether sender is on the channel */
2591 if (!silc_server_client_on_channel(client, channel)) {
2592 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2593 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2597 /* Check that client has rights to change other's rights */
2598 silc_list_start(channel->user_list);
2599 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2600 if (chl->client == client) {
2601 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2602 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2603 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2604 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2608 sender_mask = chl->mode;
2613 /* Get the target client's channel mode mask */
2614 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2616 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2617 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2620 SILC_GET32_MSB(target_mask, tmp_mask);
2622 /* Get target Client ID */
2623 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2625 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2626 SILC_STATUS_ERR_NO_CHANNEL_ID);
2629 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2631 /* Get target client's entry */
2632 target_client = silc_idlist_find_client_by_id(server->local_list,
2634 if (!target_client) {
2635 /* XXX If target client is not one of mine send to primary route */
2638 /* Check whether target client is on the channel */
2639 if (!silc_server_client_on_channel(target_client, channel)) {
2640 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2641 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2645 /* Get entry to the channel user list */
2646 silc_list_start(channel->user_list);
2647 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2648 if (chl->client == target_client)
2655 /* If the target client is founder, no one else can change their mode
2657 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2658 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2659 SILC_STATUS_ERR_NOT_YOU);
2663 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2664 /* Cannot promote anyone to channel founder */
2665 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2666 SILC_STATUS_ERR_NOT_YOU);
2669 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2670 if (target_client == client) {
2671 /* Remove channel founder rights from itself */
2672 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2675 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2676 SILC_STATUS_ERR_NOT_YOU);
2682 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2683 /* Promote to operator */
2684 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2685 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2689 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2690 /* Demote to normal user */
2691 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2696 /* Send notify to channel, notify only if mode was actually changed. */
2698 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2699 silc_server_send_notify_to_channel(server, channel, TRUE,
2700 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2701 idp->data, idp->len,
2702 tmp_mask, 4, tmp_id, tmp_len);
2703 silc_buffer_free(idp);
2706 /* Send command reply to sender */
2707 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2708 SILC_STATUS_OK, 0, 2,
2710 3, tmp_id, tmp_len);
2711 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2712 packet->data, packet->len, FALSE);
2714 silc_buffer_free(packet);
2715 silc_free(channel_id);
2716 silc_free(client_id);
2719 silc_server_command_free(cmd);
2722 /* Server side of KICK command. Kicks client out of channel. */
2724 SILC_SERVER_CMD_FUNC(kick)
2728 SILC_SERVER_CMD_FUNC(restart)
2732 SILC_SERVER_CMD_FUNC(close)
2736 SILC_SERVER_CMD_FUNC(die)
2740 SILC_SERVER_CMD_FUNC(silcoper)
2744 /* Server side command of LEAVE. Removes client from a channel. */
2746 SILC_SERVER_CMD_FUNC(leave)
2748 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2749 SilcServer server = cmd->server;
2750 SilcSocketConnection sock = cmd->sock;
2751 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2753 SilcChannelEntry channel;
2755 unsigned int i, len;
2758 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2760 /* Get Channel ID */
2761 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2764 SILC_STATUS_ERR_NO_CHANNEL_ID);
2767 id = silc_id_payload_parse_id(tmp, len);
2769 /* Get channel entry */
2770 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2773 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2777 /* Check whether this client is on the channel */
2778 if (!silc_server_client_on_channel(id_entry, channel)) {
2779 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2780 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2784 /* Notify routers that they should remove this client from their list
2785 of clients on the channel. */
2786 if (!server->standalone)
2787 silc_server_send_remove_channel_user(server,
2788 server->router->connection,
2789 server->server_type == SILC_ROUTER ?
2790 TRUE : FALSE, id_entry->id, id);
2792 /* Remove client from channel */
2793 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2798 /* If the channel does not exist anymore we won't send anything */
2802 /* Re-generate channel key */
2803 silc_server_create_channel_key(server, channel, 0);
2805 /* Encode channel key payload to be distributed on the channel */
2807 silc_channel_key_payload_encode(len, tmp,
2808 strlen(channel->channel_key->cipher->name),
2809 channel->channel_key->cipher->name,
2810 channel->key_len / 8, channel->key);
2812 /* If we are normal server then we will send it to our router. If we
2813 are router we will send it to all local servers that has clients on
2815 if (server->server_type == SILC_SERVER) {
2816 if (!server->standalone)
2817 silc_server_packet_send(server,
2818 cmd->server->router->connection,
2819 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2825 /* Send to locally connected clients on the channel */
2826 silc_server_packet_send_local_channel(server, channel,
2827 SILC_PACKET_CHANNEL_KEY, 0,
2828 packet->data, packet->len, FALSE);
2830 silc_buffer_free(packet);
2834 silc_server_command_free(cmd);
2837 /* Server side of command USERS. Resolves clients and their USERS currently
2838 joined on the requested channel. The list of Client ID's and their modes
2839 on the channel is sent back. */
2841 SILC_SERVER_CMD_FUNC(users)
2843 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2844 SilcServer server = cmd->server;
2845 SilcChannelEntry channel;
2846 SilcChannelClientEntry chl;
2850 unsigned int tmp_len;
2851 SilcBuffer client_id_list;
2852 SilcBuffer client_mode_list;
2854 unsigned short ident = silc_command_get_ident(cmd->payload);
2856 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 2);
2858 /* Get Channel ID */
2859 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2862 SILC_STATUS_ERR_NO_CHANNEL_ID);
2865 id = silc_id_payload_parse_id(tmp, tmp_len);
2867 /* If we are server and we don't know about this channel we will send
2868 the command to our router. If we know about the channel then we also
2869 have the list of users already. */
2870 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2872 if (server->server_type == SILC_SERVER && !server->standalone &&
2876 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2877 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2879 /* Send USERS command */
2880 silc_server_packet_send(server, server->router->connection,
2881 SILC_PACKET_COMMAND, cmd->packet->flags,
2882 tmpbuf->data, tmpbuf->len, TRUE);
2884 /* Reprocess this packet after received reply */
2885 silc_server_command_pending(server, SILC_COMMAND_USERS,
2886 silc_command_get_ident(cmd->payload),
2887 silc_server_command_users, (void *)cmd);
2888 cmd->pending = TRUE;
2889 silc_command_set_ident(cmd->payload, ident);
2891 silc_buffer_free(tmpbuf);
2896 /* We are router and we will check the global list as well. */
2897 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2899 /* Channel really does not exist */
2900 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2901 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2906 /* Assemble the lists now */
2908 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2909 silc_list_count(channel->user_list));
2910 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2912 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2913 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2915 silc_list_start(channel->user_list);
2916 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2918 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2919 silc_buffer_put(client_id_list, idp->data, idp->len);
2920 silc_buffer_pull(client_id_list, idp->len);
2921 silc_buffer_free(idp);
2923 /* Client's mode on channel */
2924 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2925 silc_buffer_pull(client_mode_list, 4);
2927 silc_buffer_push(client_id_list,
2928 client_id_list->data - client_id_list->head);
2929 silc_buffer_push(client_mode_list,
2930 client_mode_list->data - client_mode_list->head);
2933 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
2934 SILC_STATUS_OK, 0, 4,
2936 3, client_id_list->data,
2937 client_id_list->len,
2938 4, client_mode_list->data,
2939 client_mode_list->len);
2940 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2941 packet->data, packet->len, FALSE);
2943 silc_buffer_free(packet);
2944 silc_buffer_free(client_id_list);
2945 silc_buffer_free(client_mode_list);
2949 silc_server_command_free(cmd);