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);
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
45 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
49 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
54 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(connect, CONNECT,
56 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(restart, RESTART,
66 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
67 SILC_SERVER_CMD(close, CLOSE,
68 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
69 SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
70 SILC_SERVER_CMD(silcoper, SILCOPER,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
72 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
73 SILC_SERVER_CMD(names, NAMES, SILC_CF_LAG | SILC_CF_REG),
78 /* List of pending commands. */
79 SilcServerCommandPending *silc_command_pending = NULL;
81 /* Returns TRUE if the connection is registered. Unregistered connections
82 usually cannot send commands hence the check. */
84 static int silc_server_is_registered(SilcServer server,
85 SilcSocketConnection sock,
86 SilcServerCommandContext cmd,
90 case SILC_SOCKET_TYPE_CLIENT:
92 SilcClientEntry client = (SilcClientEntry)sock->user_data;
93 if (client->registered)
97 case SILC_SOCKET_TYPE_SERVER:
98 case SILC_SOCKET_TYPE_ROUTER:
100 SilcServerEntry serv = (SilcServerEntry)sock->user_data;
101 if (serv->registered)
109 silc_server_command_send_status_reply(cmd, command,
110 SILC_STATUS_ERR_NOT_REGISTERED);
111 silc_server_command_free(cmd);
115 /* Processes received command packet. */
117 void silc_server_command_process(SilcServer server,
118 SilcSocketConnection sock,
119 SilcPacketContext *packet)
121 SilcServerCommandContext ctx;
122 SilcServerCommand *cmd;
125 /* Check whether it is allowed for this connection to execute any
127 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
129 SilcClientEntry client = (SilcClientEntry)sock->user_data;
134 /* Allow only one command executed in 2 seconds. */
135 curtime = time(NULL);
136 if (client->last_command && (curtime - client->last_command) < 2)
139 /* Update access time */
140 client->last_command = curtime;
144 /* Allocate command context. This must be free'd by the
145 command routine receiving it. */
146 ctx = silc_calloc(1, sizeof(*ctx));
147 ctx->server = server;
149 ctx->packet = packet; /* Save original packet */
151 /* Parse the command payload in the packet */
152 ctx->payload = silc_command_payload_parse(packet->buffer);
154 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
155 silc_buffer_free(packet->buffer);
159 ctx->args = silc_command_get_args(ctx->payload);
161 /* Execute command. If this fails the packet is dropped. */
162 for (cmd = silc_command_list; cmd->cb; cmd++)
163 if (cmd->cmd == silc_command_get(ctx->payload)) {
165 if (!(cmd->flags & SILC_CF_REG)) {
170 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
177 SILC_LOG_ERROR(("Unknown command, packet dropped"));
183 silc_buffer_free(packet->buffer);
186 /* Add new pending command to the list of pending commands. Currently
187 pending commands are executed from command replies, thus we can
188 execute any command after receiving some specific command reply.
190 The argument `reply_cmd' is the command reply from where the callback
191 function is to be called, thus, it IS NOT the command to be executed. */
193 void silc_server_command_pending(SilcCommand reply_cmd,
194 SilcCommandCb callback,
197 SilcServerCommandPending *reply, *r;
199 reply = silc_calloc(1, sizeof(*reply));
200 reply->reply_cmd = reply_cmd;
201 reply->context = context;
202 reply->callback = callback;
204 if (silc_command_pending == NULL) {
205 silc_command_pending = reply;
209 for (r = silc_command_pending; r; r = r->next) {
210 if (r->next == NULL) {
217 /* Deletes pending command by reply command type. */
219 void silc_server_command_pending_del(SilcCommand reply_cmd)
221 SilcServerCommandPending *r, *tmp;
223 if (silc_command_pending) {
224 if (silc_command_pending->reply_cmd == reply_cmd) {
225 silc_free(silc_command_pending);
226 silc_command_pending = NULL;
230 for (r = silc_command_pending; r; r = r->next) {
231 if (r->next && r->next->reply_cmd == reply_cmd) {
233 r->next = r->next->next;
241 /* Free's the command context allocated before executing the command */
243 static void silc_server_command_free(SilcServerCommandContext cmd)
246 silc_command_free_payload(cmd->payload);
251 /* Sends simple status message as command reply packet */
254 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
256 SilcCommandStatus status)
260 SILC_LOG_DEBUG(("Sending command status %d", status));
262 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
263 silc_server_packet_send(cmd->server, cmd->sock,
264 SILC_PACKET_COMMAND_REPLY, 0,
265 buffer->data, buffer->len, FALSE);
266 silc_buffer_free(buffer);
269 /* Sends command status reply with one extra argument. The argument
270 type must be sent as argument. */
273 silc_server_command_send_status_data(SilcServerCommandContext cmd,
275 SilcCommandStatus status,
276 unsigned int arg_type,
278 unsigned int arg_len)
282 SILC_LOG_DEBUG(("Sending command status %d", status));
284 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
285 arg_type, arg, arg_len);
286 silc_server_packet_send(cmd->server, cmd->sock,
287 SILC_PACKET_COMMAND_REPLY, 0,
288 buffer->data, buffer->len, FALSE);
289 silc_buffer_free(buffer);
292 /* Server side of command WHOIS. Processes user's query and sends found
293 results as command replies back to the client. */
295 SILC_SERVER_CMD_FUNC(whois)
297 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
298 SilcServer server = cmd->server;
299 char *tmp, *nick = NULL, *server_name = NULL;
300 unsigned int i, argc, count = 0, len, clients_count;
302 SilcClientID *client_id = NULL;
303 SilcBuffer packet, idp;
304 SilcClientEntry *clients = NULL, entry;
305 SilcCommandStatus status;
307 SILC_LOG_DEBUG(("Start"));
309 argc = silc_argument_get_arg_num(cmd->args);
311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
312 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
317 SILC_STATUS_ERR_TOO_MANY_PARAMS);
321 /* If client ID is in the command it must be used instead of nickname */
322 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
325 /* No ID, get the nickname@server string and parse it. */
326 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
328 if (strchr(tmp, '@')) {
329 len = strcspn(tmp, "@");
330 nick = silc_calloc(len + 1, sizeof(char));
331 memcpy(nick, tmp, len);
332 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
333 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
338 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
339 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
343 /* Command includes ID, use that */
344 client_id = silc_id_payload_parse_id(tmp, len);
348 /* Get the max count of reply messages allowed */
350 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
353 SILC_STATUS_ERR_TOO_MANY_PARAMS);
357 silc_free(server_name);
363 /* Get all clients matching that nickname */
365 clients = silc_idlist_get_clients_by_nickname(server->local_list,
369 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
371 clients = silc_calloc(1, sizeof(*clients));
379 /* If we are normal server and are connected to a router we will
380 make global query from the router. */
381 if (server->server_type == SILC_SERVER && !server->standalone) {
386 /* If we are router then we will check our global list as well. */
387 if (server->server_type == SILC_ROUTER) {
389 silc_idlist_find_client_by_nickname(server->global_list,
392 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
393 SILC_STATUS_ERR_NO_SUCH_NICK,
394 3, tmp, strlen(tmp));
400 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
401 SILC_STATUS_ERR_NO_SUCH_NICK,
402 3, tmp, strlen(tmp));
408 /* XXX, works only for local server info */
410 status = SILC_STATUS_OK;
411 if (clients_count > 1)
412 status = SILC_STATUS_LIST_START;
414 for (i = 0; i < clients_count; i++) {
417 if (count && i - 1 == count)
420 if (clients_count > 2)
421 status = SILC_STATUS_LIST_ITEM;
423 if (clients_count > 1 && i == clients_count - 1)
424 status = SILC_STATUS_LIST_END;
426 /* Send WHOIS reply */
427 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
428 tmp = silc_argument_get_first_arg(cmd->args, NULL);
431 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
432 char nh[256], uh[256];
433 unsigned char idle[4];
434 SilcSocketConnection hsock;
436 memset(uh, 0, sizeof(uh));
437 memset(nh, 0, sizeof(nh));
439 strncat(nh, entry->nickname, strlen(entry->nickname));
441 len = entry->router ? strlen(entry->router->server_name) :
442 strlen(server->server_name);
443 strncat(nh, entry->router ? entry->router->server_name :
444 server->server_name, len);
446 strncat(uh, entry->username, strlen(entry->username));
448 hsock = (SilcSocketConnection)entry->connection;
449 len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
450 strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
452 SILC_PUT32_MSB((time(NULL) - entry->last_receive), idle);
457 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
459 2, idp->data, idp->len,
463 strlen(entry->userinfo),
467 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
469 2, idp->data, idp->len,
477 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
479 2, idp->data, idp->len,
481 strlen(entry->nickname),
482 4, tmp, strlen(tmp)); /* XXX */
484 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
485 0, packet->data, packet->len, FALSE);
487 silc_buffer_free(packet);
488 silc_buffer_free(idp);
493 silc_free(client_id);
496 silc_server_command_free(cmd);
499 SILC_SERVER_CMD_FUNC(whowas)
503 SILC_SERVER_CMD_FUNC(identify)
505 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
506 SilcServer server = cmd->server;
507 char *tmp, *nick = NULL, *server_name = NULL;
508 unsigned int argc, count = 0, len;
510 SilcClientID *client_id = NULL;
511 SilcClientEntry entry;
512 SilcBuffer packet, idp;
514 SILC_LOG_DEBUG(("Start"));
516 argc = silc_argument_get_arg_num(cmd->args);
518 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
519 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
523 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
524 SILC_STATUS_ERR_TOO_MANY_PARAMS);
528 /* If client ID is in the command it must be used instead of nickname */
529 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
532 /* Get the nickname@server string and parse it. */
533 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
535 if (strchr(tmp, '@')) {
536 len = strcspn(tmp, "@");
537 nick = silc_calloc(len + 1, sizeof(char));
538 memcpy(nick, tmp, len);
539 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
540 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
545 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
546 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
550 /* Command includes ID, use that */
551 client_id = silc_id_payload_parse_id(tmp, len);
555 /* Get the max count of reply messages allowed */
557 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
560 SILC_STATUS_ERR_TOO_MANY_PARAMS);
568 entry = silc_idlist_find_client_by_nickname(server->local_list,
571 entry = silc_idlist_find_client_by_hash(server->global_list,
572 nick, server->md5hash);
574 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
577 /* If client was not found and if we are normal server and are connected
578 to a router we will make global query from the router. */
579 if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
581 SilcBuffer buffer = cmd->packet->buffer;
583 SILC_LOG_DEBUG(("Requesting identify from router"));
585 /* Send IDENTIFY command to our router */
586 silc_buffer_push(buffer, buffer->data - buffer->head);
587 silc_server_packet_forward(server, (SilcSocketConnection)
588 server->id_entry->router->connection,
589 buffer->data, buffer->len, TRUE);
593 /* If we are router we have checked our local list by nickname and our
594 global list by hash so far. It is possible that the client is still not
595 found and we'll check it from local list by hash. */
596 if (!entry && server->server_type == SILC_ROUTER)
597 entry = silc_idlist_find_client_by_hash(server->local_list,
598 nick, server->md5hash);
601 /* The client definitely does not exist */
602 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
603 SILC_STATUS_ERR_NO_SUCH_NICK,
604 3, tmp, strlen(tmp));
608 /* Send IDENTIFY reply */
609 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
610 tmp = silc_argument_get_first_arg(cmd->args, NULL);
611 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
612 SILC_STATUS_OK, 0, 2,
613 2, idp->data, idp->len,
614 3, nick, strlen(nick));
615 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
616 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
617 silc_server_packet_send_dest(server, cmd->sock,
618 SILC_PACKET_COMMAND_REPLY, 0,
619 id, cmd->packet->src_id_type,
620 packet->data, packet->len, FALSE);
623 silc_server_packet_send(server, cmd->sock,
624 SILC_PACKET_COMMAND_REPLY, 0,
625 packet->data, packet->len, FALSE);
628 silc_buffer_free(packet);
629 silc_buffer_free(idp);
631 silc_free(client_id);
637 silc_free(server_name);
638 silc_server_command_free(cmd);
641 /* Checks string for bad characters and returns TRUE if they are found. */
643 static int silc_server_command_bad_chars(char *nick)
645 if (strchr(nick, '\\')) return TRUE;
646 if (strchr(nick, '\"')) return TRUE;
647 if (strchr(nick, '´')) return TRUE;
648 if (strchr(nick, '`')) return TRUE;
649 if (strchr(nick, '\'')) return TRUE;
650 if (strchr(nick, '*')) return TRUE;
651 if (strchr(nick, '/')) return TRUE;
652 if (strchr(nick, '@')) return TRUE;
657 /* Server side of command NICK. Sets nickname for user. Setting
658 nickname causes generation of a new client ID for the client. The
659 new client ID is sent to the client after changing the nickname. */
661 SILC_SERVER_CMD_FUNC(nick)
663 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
664 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
665 SilcServer server = cmd->server;
666 SilcBuffer packet, nidp, oidp;
667 SilcClientID *new_id;
670 SILC_LOG_DEBUG(("Start"));
672 /* Check number of arguments */
673 if (silc_argument_get_arg_num(cmd->args) < 1) {
674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
675 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
680 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
681 if (silc_server_command_bad_chars(nick) == TRUE) {
682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
683 SILC_STATUS_ERR_BAD_NICKNAME);
687 /* Create new Client ID */
688 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
689 cmd->server->md5hash, nick,
692 /* Send notify about nickname change to our router. We send the new
693 ID and ask to replace it with the old one. */
694 if (cmd->server->server_type == SILC_SERVER && !cmd->server->standalone)
695 silc_server_send_replace_id(server, server->id_entry->router->connection,
697 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
698 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
700 /* If we are router we have to distribute the new Client ID to all
702 if (cmd->server->server_type == SILC_ROUTER && !cmd->server->standalone)
703 silc_server_send_replace_id(server, server->id_entry->router->connection,
705 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
706 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
708 /* Remove old cache entry */
709 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
712 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
716 memset(client->id, 0, SILC_ID_CLIENT_LEN);
717 silc_free(client->id);
720 /* Save the nickname as this client is our local client */
721 if (client->nickname)
722 silc_free(client->nickname);
724 client->nickname = strdup(nick);
727 /* Update client cache */
728 silc_idcache_add(server->local_list->clients, client->nickname,
729 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
731 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
733 /* Send NICK_CHANGE notify */
734 silc_server_send_notify_on_channels(server, client,
735 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
736 oidp->data, oidp->len,
737 nidp->data, nidp->len);
739 /* Send the new Client ID as reply command back to client */
740 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
741 SILC_STATUS_OK, 0, 1,
742 2, nidp->data, nidp->len);
743 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
744 0, packet->data, packet->len, FALSE);
746 silc_buffer_free(packet);
747 silc_buffer_free(nidp);
748 silc_buffer_free(oidp);
751 silc_server_command_free(cmd);
754 SILC_SERVER_CMD_FUNC(list)
758 /* Server side of TOPIC command. Sets topic for channel and/or returns
759 current topic to client. */
761 SILC_SERVER_CMD_FUNC(topic)
763 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
764 SilcServer server = cmd->server;
765 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
766 SilcChannelID *channel_id;
767 SilcChannelEntry channel;
768 SilcChannelClientEntry chl;
769 SilcBuffer packet, idp;
771 unsigned int argc, tmp_len;
773 /* Check number of arguments */
774 argc = silc_argument_get_arg_num(cmd->args);
776 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
777 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
781 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
782 SILC_STATUS_ERR_TOO_MANY_PARAMS);
787 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
789 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
790 SILC_STATUS_ERR_NO_CHANNEL_ID);
793 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
795 /* Check whether the channel exists */
796 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
798 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
799 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
805 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
807 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
808 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
812 if (strlen(tmp) > 256) {
813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
814 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
818 /* See whether has rights to change topic */
819 silc_list_start(channel->user_list);
820 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
821 if (chl->client == client) {
822 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
824 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
832 /* Set the topic for channel */
834 silc_free(channel->topic);
835 channel->topic = strdup(tmp);
837 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
839 /* Send notify about topic change to all clients on the channel */
840 silc_server_send_notify_to_channel(server, channel,
841 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
843 channel->topic, strlen(channel->topic));
844 silc_buffer_free(idp);
847 /* Send the topic to client as reply packet */
848 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
850 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
851 SILC_STATUS_OK, 0, 2,
852 2, idp->data, idp->len,
854 strlen(channel->topic));
856 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
857 SILC_STATUS_OK, 0, 1,
858 2, idp->data, idp->len);
859 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
860 0, packet->data, packet->len, FALSE);
862 silc_buffer_free(packet);
863 silc_buffer_free(idp);
864 silc_free(channel_id);
867 silc_server_command_free(cmd);
870 /* Server side of INVITE command. Invites some client to join some channel. */
872 SILC_SERVER_CMD_FUNC(invite)
874 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
875 SilcServer server = cmd->server;
876 SilcSocketConnection sock = cmd->sock, dest_sock;
877 SilcClientEntry sender, dest;
878 SilcClientID *dest_id;
879 SilcChannelEntry channel;
880 SilcChannelID *channel_id;
883 unsigned int argc, len;
885 /* Check number of arguments */
886 argc = silc_argument_get_arg_num(cmd->args);
888 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
889 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
893 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
894 SILC_STATUS_ERR_TOO_MANY_PARAMS);
898 /* Get destination ID */
899 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
902 SILC_STATUS_ERR_NO_CLIENT_ID);
905 dest_id = silc_id_payload_parse_id(tmp, len);
908 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
910 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
911 SILC_STATUS_ERR_NO_CHANNEL_ID);
914 channel_id = silc_id_payload_parse_id(tmp, len);
916 /* Check whether the channel exists */
917 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
919 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
920 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
924 /* Check whether the sender of this command is on the channel. */
925 sender = (SilcClientEntry)sock->user_data;
926 if (!silc_server_client_on_channel(sender, channel)) {
927 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
928 SILC_STATUS_ERR_NOT_ON_CHANNEL);
932 /* Check whether the channel is invite-only channel. If yes then the
933 sender of this command must be at least channel operator. */
934 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
935 SilcChannelClientEntry chl;
937 silc_list_start(channel->user_list);
938 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
939 if (chl->client == sender) {
940 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
942 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
949 /* Find the connection data for the destination. If it is local we will
950 send it directly otherwise we will send it to router for routing. */
951 dest = silc_idlist_find_client_by_id(server->local_list, dest_id);
953 dest_sock = (SilcSocketConnection)dest->connection;
955 dest_sock = silc_server_get_route(server, dest_id, SILC_ID_CLIENT);
957 /* Check whether the requested client is already on the channel. */
958 /* XXX if we are normal server we don't know about global clients on
959 the channel thus we must request it (NAMES command), check from
960 local cache as well. */
961 if (silc_server_client_on_channel(dest, channel)) {
962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
963 SILC_STATUS_ERR_USER_ON_CHANNEL);
967 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
969 /* Send notify to the client that is invited to the channel */
970 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
971 SILC_NOTIFY_TYPE_INVITE, 2,
972 sidp->data, sidp->len, tmp, len);
974 /* Send command reply */
975 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
978 silc_buffer_free(sidp);
981 silc_server_command_free(cmd);
984 /* Quits connection to client. This gets called if client won't
985 close the connection even when it has issued QUIT command. */
987 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
989 SilcServer server = (SilcServer)context;
990 SilcSocketConnection sock = server->sockets[fd];
992 /* Free all client specific data, such as client entry and entires
993 on channels this client may be on. */
994 silc_server_free_sock_user_data(server, sock);
996 /* Close the connection on our side */
997 silc_server_close_connection(server, sock);
1000 /* Quits SILC session. This is the normal way to disconnect client. */
1002 SILC_SERVER_CMD_FUNC(quit)
1004 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1005 SilcServer server = cmd->server;
1006 SilcSocketConnection sock = cmd->sock;
1008 SILC_LOG_DEBUG(("Start"));
1010 /* We quit the connection with little timeout */
1011 silc_task_register(server->timeout_queue, sock->sock,
1012 silc_server_command_quit_cb, server,
1013 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1015 silc_server_command_free(cmd);
1018 SILC_SERVER_CMD_FUNC(kill)
1022 /* Server side of command INFO. This sends information about us to
1023 the client. If client requested specific server we will send the
1024 command to that server. */
1026 SILC_SERVER_CMD_FUNC(info)
1028 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1029 SilcServer server = cmd->server;
1030 SilcBuffer packet, idp;
1032 char info_string[256], *dest_server;
1034 argc = silc_argument_get_arg_num(cmd->args);
1036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1037 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1041 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1042 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1046 /* Get server name */
1047 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1050 SILC_STATUS_ERR_NO_SUCH_SERVER);
1054 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1055 /* Send our reply */
1056 memset(info_string, 0, sizeof(info_string));
1057 snprintf(info_string, sizeof(info_string),
1058 "location: %s server: %s admin: %s <%s>",
1059 server->config->admin_info->location,
1060 server->config->admin_info->server_type,
1061 server->config->admin_info->admin_name,
1062 server->config->admin_info->admin_email);
1064 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1066 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1067 SILC_STATUS_OK, 0, 2,
1068 2, idp->data, idp->len,
1070 strlen(info_string));
1071 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1072 packet->data, packet->len, FALSE);
1074 silc_buffer_free(packet);
1075 silc_buffer_free(idp);
1077 /* Send this command to the requested server */
1079 if (server->server_type == SILC_SERVER && !server->standalone) {
1083 if (server->server_type == SILC_ROUTER) {
1089 silc_server_command_free(cmd);
1092 SILC_SERVER_CMD_FUNC(connect)
1096 /* Server side of command PING. This just replies to the ping. */
1098 SILC_SERVER_CMD_FUNC(ping)
1100 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1101 SilcServer server = cmd->server;
1103 unsigned int argc, len;
1106 argc = silc_argument_get_arg_num(cmd->args);
1108 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1109 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1113 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1114 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1119 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1122 SILC_STATUS_ERR_NO_SERVER_ID);
1125 id = silc_id_payload_parse_id(tmp, len);
1127 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1128 /* Send our reply */
1129 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1132 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1133 SILC_STATUS_ERR_NO_SUCH_SERVER);
1140 silc_server_command_free(cmd);
1143 SILC_SERVER_CMD_FUNC(oper)
1152 SilcChannelEntry channel;
1154 SilcClientEntry client;
1155 } JoinInternalContext;
1157 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1159 JoinInternalContext *ctx = (JoinInternalContext *)context;
1161 if (ctx->channel->key && ctx->channel->key_len) {
1164 clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1166 silc_server_send_notify_to_channel(ctx->server, ctx->channel,
1167 SILC_NOTIFY_TYPE_JOIN, 1,
1168 clidp->data, clidp->len);
1170 silc_buffer_free(clidp);
1173 silc_task_register(ctx->server->timeout_queue, fd,
1174 silc_server_command_join_notify, context,
1175 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1179 /* Assembles NAMES command and executes it. This is called when client
1180 joins to a channel and we wan't to send NAMES command reply to the
1183 void silc_server_command_send_names(SilcServer server,
1184 SilcSocketConnection sock,
1185 SilcChannelEntry channel)
1187 SilcServerCommandContext cmd;
1188 SilcBuffer buffer, idp;
1190 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1191 buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1192 1, idp->data, idp->len);
1194 cmd = silc_calloc(1, sizeof(*cmd));
1195 cmd->payload = silc_command_payload_parse(buffer);
1196 cmd->args = silc_command_get_args(cmd->payload);
1197 cmd->server = server;
1199 cmd->pending = FALSE;
1201 silc_server_command_names((void *)cmd);
1206 /* Server side of command JOIN. Joins client into requested channel. If
1207 the channel does not exist it will be created. */
1209 SILC_SERVER_CMD_FUNC(join)
1211 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1212 SilcServer server = cmd->server;
1213 SilcSocketConnection sock = cmd->sock;
1214 SilcBuffer buffer = cmd->packet->buffer;
1215 int argc, i, k, tmp_len;
1216 char *tmp, *channel_name = NULL, *cipher = NULL;
1217 unsigned char *passphrase = NULL, mode[4];
1218 unsigned int umode = 0;
1219 SilcChannelEntry channel;
1220 SilcChannelClientEntry chl;
1221 SilcServerID *router_id;
1222 SilcBuffer packet, idp;
1223 SilcClientEntry client;
1225 SILC_LOG_DEBUG(("Start"));
1227 /* Check number of parameters */
1228 argc = silc_argument_get_arg_num(cmd->args);
1230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1231 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1235 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1236 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1240 /* Get channel name */
1241 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1244 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1249 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1250 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1251 SILC_STATUS_ERR_BAD_CHANNEL);
1252 silc_free(channel_name);
1256 /* Get passphrase */
1257 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1259 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1260 memcpy(passphrase, tmp, tmp_len);
1263 /* Get cipher name */
1264 cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1266 /* See if the channel exists */
1268 silc_idlist_find_channel_by_name(server->local_list, channel_name);
1270 /* Channel not found */
1272 /* If we are standalone server we don't have a router, we just create
1273 the channel by ourselves. */
1274 if (server->standalone) {
1275 router_id = server->id;
1276 channel = silc_server_new_channel(server, router_id, cipher,
1278 umode |= SILC_CHANNEL_UMODE_CHANOP;
1279 umode |= SILC_CHANNEL_UMODE_CHANFO;
1286 /* No channel ID found, the channel does not exist on our server.
1287 We send JOIN command to our router which will handle the joining
1288 procedure (either creates the channel if it doesn't exist or
1289 joins the client to it) - if we are normal server. */
1290 if (server->server_type == SILC_SERVER) {
1292 /* Forward the original JOIN command to the router */
1293 silc_buffer_push(buffer, buffer->data - buffer->head);
1294 silc_server_packet_forward(server, (SilcSocketConnection)
1295 server->id_entry->router->connection,
1296 buffer->data, buffer->len, TRUE);
1298 /* Add the command to be pending. It will be re-executed after
1299 router has replied back to us. */
1300 cmd->pending = TRUE;
1301 silc_server_command_pending(SILC_COMMAND_JOIN,
1302 silc_server_command_join, context);
1307 /* If we are router and the channel does not exist we will check our
1308 global list for the channel. */
1309 if (!channel && server->server_type == SILC_ROUTER) {
1311 /* Notify all routers about the new channel in SILC network. */
1312 if (!server->standalone) {
1314 silc_server_send_new_id(server, server->id_entry->router->connection,
1316 xxx, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN);
1325 * Check channel modes
1328 /* Check invite list if channel is invite-only channel */
1329 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1330 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1331 /* Invite list is specified. Check whether client is invited in the
1332 list. If not, then check whether it has been invited otherwise. */
1335 /* XXX client must be invited to be able to join the channel */
1339 /* Check ban list if set */
1340 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1344 /* Check the channel passphrase if set. */
1345 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1346 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1347 strlen(channel->mode_data.passphrase))) {
1348 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1349 SILC_STATUS_ERR_BAD_PASSWORD);
1354 /* Check user count limit if set. */
1355 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1356 if (silc_list_count(channel->user_list) + 1 >
1357 channel->mode_data.user_limit) {
1358 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1359 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1365 * Client is allowed to join to the channel. Make it happen.
1368 /* If the JOIN request was forwarded to us we will make a bit slower
1369 query to get the client pointer. Otherwise, we get the client pointer
1371 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1372 client = (SilcClientEntry)sock->user_data;
1374 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1375 client = silc_idlist_find_client_by_id(server->local_list, id);
1383 /* Check whether the client already is on the channel */
1384 if (silc_server_client_on_channel(client, channel)) {
1385 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1386 SILC_STATUS_ERR_USER_ON_CHANNEL);
1390 /* Join the client to the channel by adding it to channel's user list */
1391 chl = silc_calloc(1, sizeof(*chl));
1393 chl->client = client;
1394 silc_list_add(channel->user_list, chl);
1396 /* Add the channel to client's channel list */
1397 i = client->channel_count;
1398 for (k = 0; k < client->channel_count; k++) {
1399 if (client->channel[k] == NULL) {
1400 client->channel[k] = channel;
1405 i = client->channel_count;
1406 client->channel = silc_realloc(client->channel,
1407 sizeof(*client->channel) * (i + 1));
1408 client->channel[i] = channel;
1409 client->channel_count++;
1412 /* Notify router about new user on channel. If we are normal server
1413 we send it to our router, if we are router we send it to our
1415 if (!server->standalone) {
1419 /* Send command reply to the client. Client receives the Channe ID,
1420 channel mode and possibly other information in this reply packet. */
1421 if (!cmd->pending) {
1422 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1423 SILC_PUT32_MSB(channel->mode, mode);
1425 if (!channel->topic)
1427 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1428 SILC_STATUS_OK, 0, 3,
1430 strlen(channel_name),
1431 3, idp->data, idp->len,
1435 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1436 SILC_STATUS_OK, 0, 4,
1438 strlen(channel_name),
1439 3, idp->data, idp->len,
1442 strlen(channel->topic));
1444 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1445 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1446 silc_server_packet_send_dest(cmd->server, cmd->sock,
1447 SILC_PACKET_COMMAND_REPLY, 0,
1448 id, cmd->packet->src_id_type,
1449 packet->data, packet->len, FALSE);
1452 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1453 packet->data, packet->len, FALSE);
1454 silc_buffer_free(packet);
1456 /* Send channel key to the client. Client cannot start transmitting
1457 to the channel until we have sent the key. */
1458 tmp_len = strlen(channel->channel_key->cipher->name);
1460 silc_channel_key_payload_encode(idp->len, idp->data,
1461 strlen(channel->channel_key->
1463 channel->channel_key->cipher->name,
1464 channel->key_len / 8, channel->key);
1466 silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
1467 packet->data, packet->len, FALSE);
1469 silc_buffer_free(packet);
1470 silc_buffer_free(idp);
1473 /* Finally, send notify message to all clients on the channel about
1474 new user on the channel. */
1475 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1476 if (!cmd->pending) {
1479 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1481 silc_server_send_notify_to_channel(server, channel,
1482 SILC_NOTIFY_TYPE_JOIN, 1,
1483 clidp->data, clidp->len);
1485 silc_buffer_free(clidp);
1487 /* This is pending command request. Send the notify after we have
1488 received the key for the channel from the router. */
1489 JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
1490 ctx->channel_name = channel_name;
1491 ctx->nickname = client->nickname;
1492 ctx->username = client->username;
1493 ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
1494 ctx->channel = channel;
1495 ctx->server = server;
1496 ctx->client = client;
1497 silc_task_register(server->timeout_queue, sock->sock,
1498 silc_server_command_join_notify, ctx,
1499 0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1503 /* Send NAMES command reply to the joined channel so the user sees who
1504 is currently on the channel. */
1505 silc_server_command_send_names(server, sock, channel);
1508 silc_server_command_free(cmd);
1511 /* Server side of command MOTD. Sends server's current "message of the
1512 day" to the client. */
1514 SILC_SERVER_CMD_FUNC(motd)
1516 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1517 SilcServer server = cmd->server;
1522 SILC_LOG_DEBUG(("Start"));
1524 argc = silc_argument_get_arg_num(cmd->args);
1526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1527 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1532 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1536 /* XXX show currently only our motd */
1538 if (server->config && server->config->motd &&
1539 server->config->motd->motd_file) {
1542 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
1547 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
1553 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
1558 silc_server_command_free(cmd);
1561 SILC_SERVER_CMD_FUNC(umode)
1565 /* Checks that client has rights to add or remove channel modes. If any
1566 of the checks fails FALSE is returned. */
1568 int silc_server_check_cmode_rights(SilcChannelEntry channel,
1569 SilcChannelClientEntry client,
1572 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1573 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1575 /* Check whether has rights to change anything */
1576 if (!is_op && !is_fo)
1579 /* Check whether has rights to change everything */
1583 /* We know that client is channel operator, check that they are not
1584 changing anything that requires channel founder rights. Rest of the
1585 modes are available automatically for channel operator. */
1587 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1588 if (is_op && !is_fo)
1591 if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
1592 if (is_op && !is_fo)
1597 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1598 if (is_op && !is_fo)
1601 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1602 if (is_op && !is_fo)
1607 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1608 if (is_op && !is_fo)
1611 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1612 if (is_op && !is_fo)
1620 /* Server side command of CMODE. Changes channel mode */
1622 SILC_SERVER_CMD_FUNC(cmode)
1624 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1625 SilcServer server = cmd->server;
1626 SilcSocketConnection sock = cmd->sock;
1627 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1628 SilcChannelID *channel_id;
1629 SilcClientID *client_id;
1630 SilcChannelEntry channel;
1631 SilcChannelClientEntry chl;
1632 SilcBuffer packet, cidp;
1633 unsigned char *tmp, *tmp_id, *tmp_mask;
1634 unsigned int argc, mode_mask, tmp_len, tmp_len2;
1637 SILC_LOG_DEBUG(("Start"));
1639 argc = silc_argument_get_arg_num(cmd->args);
1641 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1642 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1646 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1647 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1651 /* Get Channel ID */
1652 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
1654 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1655 SILC_STATUS_ERR_NO_CHANNEL_ID);
1658 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
1660 /* Get the channel mode mask */
1661 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1663 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1664 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1667 SILC_GET32_MSB(mode_mask, tmp_mask);
1669 /* Get channel entry */
1670 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1673 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1677 /* Check whether this client is on the channel */
1678 if (!silc_server_client_on_channel(client, channel)) {
1679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1680 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1684 /* Get entry to the channel user list */
1685 silc_list_start(channel->user_list);
1686 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1687 if (chl->client == client)
1690 /* Check that client has rights to change any requested channel modes */
1691 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
1692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1693 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1698 * Check the modes. Modes that requires nothing special operation are
1702 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
1703 /* Channel uses private keys to protect traffic. Client(s) has set the
1704 key locally they want to use, server does not know that key. */
1705 /* Nothing interesting to do here now */
1707 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1708 /* The mode is removed and we need to generate and distribute
1709 new channel key. Clients are not using private channel keys
1710 anymore after this. */
1711 unsigned int key_len;
1712 unsigned char channel_key[32];
1714 /* XXX Duplicated code, make own function for this!! LEAVE uses this
1717 /* Re-generate channel key */
1718 key_len = channel->key_len / 8;
1719 for (i = 0; i < key_len; i++)
1720 channel_key[i] = silc_rng_get_byte(server->rng);
1721 channel->channel_key->cipher->set_key(channel->channel_key->context,
1722 channel_key, key_len);
1723 memset(channel->key, 0, key_len);
1724 silc_free(channel->key);
1725 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1726 memcpy(channel->key, channel_key, key_len);
1727 memset(channel_key, 0, sizeof(channel_key));
1729 /* Encode channel key payload to be distributed on the channel */
1731 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1732 strlen(channel->channel_key->
1734 channel->channel_key->cipher->name,
1735 key_len, channel->key);
1737 /* If we are normal server then we will send it to our router. If we
1738 are router we will send it to all local servers that has clients on
1740 if (server->server_type == SILC_SERVER) {
1741 if (!server->standalone)
1742 silc_server_packet_send(server,
1743 cmd->server->id_entry->router->connection,
1744 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1750 /* Send to locally connected clients on the channel */
1751 silc_server_packet_send_local_channel(server, channel,
1752 SILC_PACKET_CHANNEL_KEY, 0,
1753 packet->data, packet->len, FALSE);
1754 silc_buffer_free(packet);
1758 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
1759 /* User limit is set on channel */
1760 unsigned int user_limit;
1762 /* Get user limit */
1763 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1765 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
1766 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1767 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1771 SILC_GET32_MSB(user_limit, tmp);
1772 channel->mode_data.user_limit = user_limit;
1775 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
1776 /* User limit mode is unset. Remove user limit */
1777 channel->mode_data.user_limit = 0;
1780 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
1781 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1782 /* Passphrase has been set to channel */
1784 /* Get the passphrase */
1785 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1788 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1792 /* Save the passphrase */
1793 channel->mode_data.passphrase = strdup(tmp);
1796 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1797 /* Passphrase mode is unset. remove the passphrase */
1798 if (channel->mode_data.passphrase) {
1799 silc_free(channel->mode_data.passphrase);
1800 channel->mode_data.passphrase = NULL;
1805 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
1806 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
1807 /* Ban list is specified for channel */
1810 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1813 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1817 /* XXX check that channel founder is not banned */
1819 /* Save the ban list */
1820 channel->mode_data.ban_list = strdup(tmp);
1823 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1824 /* Ban mode is unset. Remove the entire ban list */
1825 if (channel->mode_data.ban_list) {
1826 silc_free(channel->mode_data.ban_list);
1827 channel->mode_data.ban_list = NULL;
1832 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
1833 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
1834 /* Invite list is specified for channel */
1836 /* Get invite list */
1837 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1839 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1840 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1844 /* Save the invite linst */
1845 channel->mode_data.invite_list = strdup(tmp);
1848 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1849 /* Invite list mode is unset. Remove the entire invite list */
1850 if (channel->mode_data.invite_list) {
1851 silc_free(channel->mode_data.invite_list);
1852 channel->mode_data.invite_list = NULL;
1857 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
1858 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1859 /* Cipher to use protect the traffic */
1860 unsigned int key_len = 128;
1861 unsigned char channel_key[32];
1865 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
1867 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1868 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1872 cp = strchr(tmp, ':');
1878 /* XXX Duplicated code, make own function for this!! */
1880 /* Delete old cipher and allocate the new one */
1881 silc_cipher_free(channel->channel_key);
1882 silc_cipher_alloc(tmp, &channel->channel_key);
1884 /* Re-generate channel key */
1886 if (key_len > sizeof(channel_key))
1887 key_len = sizeof(channel_key);
1889 for (i = 0; i < key_len; i++)
1890 channel_key[i] = silc_rng_get_byte(server->rng);
1891 channel->channel_key->cipher->set_key(channel->channel_key->context,
1892 channel_key, key_len);
1893 memset(channel->key, 0, key_len);
1894 silc_free(channel->key);
1895 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1896 memcpy(channel->key, channel_key, key_len);
1897 memset(channel_key, 0, sizeof(channel_key));
1899 /* Encode channel key payload to be distributed on the channel */
1901 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1902 strlen(channel->channel_key->
1904 channel->channel_key->cipher->name,
1905 key_len, channel->key);
1907 /* If we are normal server then we will send it to our router. If we
1908 are router we will send it to all local servers that has clients on
1910 if (server->server_type == SILC_SERVER) {
1911 if (!server->standalone)
1912 silc_server_packet_send(server,
1913 cmd->server->id_entry->router->connection,
1914 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1920 /* Send to locally connected clients on the channel */
1921 silc_server_packet_send_local_channel(server, channel,
1922 SILC_PACKET_CHANNEL_KEY, 0,
1923 packet->data, packet->len, FALSE);
1924 silc_buffer_free(packet);
1927 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1928 /* Cipher mode is unset. Remove the cipher and revert back to
1930 unsigned int key_len;
1931 unsigned char channel_key[32];
1933 if (channel->mode_data.cipher) {
1934 silc_free(channel->mode_data.cipher);
1935 channel->mode_data.cipher = NULL;
1936 channel->mode_data.key_len = 0;
1939 /* Generate new cipher and key for the channel */
1941 /* XXX Duplicated code, make own function for this!! */
1943 /* Delete old cipher and allocate default one */
1944 silc_cipher_free(channel->channel_key);
1945 if (!channel->cipher)
1946 silc_cipher_alloc("twofish", &channel->channel_key);
1948 silc_cipher_alloc(channel->cipher, &channel->channel_key);
1950 /* Re-generate channel key */
1951 key_len = channel->key_len / 8;
1952 for (i = 0; i < key_len; i++)
1953 channel_key[i] = silc_rng_get_byte(server->rng);
1954 channel->channel_key->cipher->set_key(channel->channel_key->context,
1955 channel_key, key_len);
1956 memset(channel->key, 0, key_len);
1957 silc_free(channel->key);
1958 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1959 memcpy(channel->key, channel_key, key_len);
1960 memset(channel_key, 0, sizeof(channel_key));
1962 /* Encode channel key payload to be distributed on the channel */
1964 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1965 strlen(channel->channel_key->
1967 channel->channel_key->cipher->name,
1968 key_len, channel->key);
1970 /* If we are normal server then we will send it to our router. If we
1971 are router we will send it to all local servers that has clients on
1973 if (server->server_type == SILC_SERVER) {
1974 if (!server->standalone)
1975 silc_server_packet_send(server,
1976 cmd->server->id_entry->router->connection,
1977 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1983 /* Send to locally connected clients on the channel */
1984 silc_server_packet_send_local_channel(server, channel,
1985 SILC_PACKET_CHANNEL_KEY, 0,
1986 packet->data, packet->len, FALSE);
1987 silc_buffer_free(packet);
1991 /* Finally, set the mode */
1992 channel->mode = mode_mask;
1994 /* Send CMODE_CHANGE notify */
1995 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1996 silc_server_send_notify_to_channel(server, channel,
1997 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
1998 cidp->data, cidp->len,
2002 /* Send command reply to sender */
2003 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2004 SILC_STATUS_OK, 0, 1,
2006 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2007 packet->data, packet->len, FALSE);
2009 silc_buffer_free(packet);
2010 silc_free(channel_id);
2013 silc_server_command_free(cmd);
2016 /* Server side of CUMODE command. Changes client's mode on a channel. */
2018 SILC_SERVER_CMD_FUNC(cumode)
2020 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2021 SilcServer server = cmd->server;
2022 SilcSocketConnection sock = cmd->sock;
2023 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2024 SilcChannelID *channel_id;
2025 SilcClientID *client_id;
2026 SilcChannelEntry channel;
2027 SilcClientEntry target_client;
2028 SilcChannelClientEntry chl;
2029 SilcBuffer packet, idp;
2030 unsigned char *tmp, *tmp_id, *tmp_mask;
2031 unsigned int argc, target_mask, sender_mask, tmp_len;
2032 int i, notify = FALSE;
2034 SILC_LOG_DEBUG(("Start"));
2036 argc = silc_argument_get_arg_num(cmd->args);
2038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2039 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2044 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2048 /* Get Channel ID */
2049 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2052 SILC_STATUS_ERR_NO_CHANNEL_ID);
2055 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2057 /* Get channel entry */
2058 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
2060 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2061 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2065 /* Check whether sender is on the channel */
2066 if (!silc_server_client_on_channel(client, channel)) {
2067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2068 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2072 /* Check that client has rights to change other's rights */
2073 silc_list_start(channel->user_list);
2074 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2075 if (chl->client == client) {
2076 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2077 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2079 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2083 sender_mask = chl->mode;
2088 /* Get the target client's channel mode mask */
2089 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2092 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2095 SILC_GET32_MSB(target_mask, tmp_mask);
2097 /* Get target Client ID */
2098 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2100 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2101 SILC_STATUS_ERR_NO_CHANNEL_ID);
2104 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2106 /* Get target client's entry */
2107 target_client = silc_idlist_find_client_by_id(server->local_list, client_id);
2109 /* XXX If target client is not one of mine send to primary route */
2112 /* Check whether target client is on the channel */
2113 if (!silc_server_client_on_channel(target_client, channel)) {
2114 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2115 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2119 /* Get entry to the channel user list */
2120 silc_list_start(channel->user_list);
2121 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2122 if (chl->client == target_client)
2129 /* If the target client is founder, no one else can change their mode
2131 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2132 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2133 SILC_STATUS_ERR_NOT_YOU);
2137 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2138 /* Cannot promote anyone to channel founder */
2139 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2140 SILC_STATUS_ERR_NOT_YOU);
2143 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2144 if (target_client == client) {
2145 /* Remove channel founder rights from itself */
2146 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2149 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2150 SILC_STATUS_ERR_NOT_YOU);
2156 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2157 /* Promote to operator */
2158 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2159 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2163 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2164 /* Demote to normal user */
2165 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2170 /* Send notify to channel, notify only if mode was actually changed. */
2172 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2173 silc_server_send_notify_to_channel(server, channel,
2174 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2175 idp->data, idp->len,
2176 tmp_mask, 4, tmp_id, tmp_len);
2177 silc_buffer_free(idp);
2180 /* Send command reply to sender */
2181 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2182 SILC_STATUS_OK, 0, 2,
2184 3, tmp_id, tmp_len);
2185 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2186 packet->data, packet->len, FALSE);
2188 silc_buffer_free(packet);
2189 silc_free(channel_id);
2190 silc_free(client_id);
2193 silc_server_command_free(cmd);
2196 /* Server side of KICK command. Kicks client out of channel. */
2198 SILC_SERVER_CMD_FUNC(kick)
2200 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2201 SilcServer server = cmd->server;
2202 SilcSocketConnection sock = cmd->sock;
2203 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2207 SILC_SERVER_CMD_FUNC(restart)
2211 SILC_SERVER_CMD_FUNC(close)
2215 SILC_SERVER_CMD_FUNC(die)
2219 SILC_SERVER_CMD_FUNC(silcoper)
2223 /* Server side command of LEAVE. Removes client from a channel. */
2225 SILC_SERVER_CMD_FUNC(leave)
2227 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2228 SilcServer server = cmd->server;
2229 SilcSocketConnection sock = cmd->sock;
2230 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2232 SilcChannelEntry channel;
2234 unsigned int i, argc, key_len, len;
2235 unsigned char *tmp, channel_key[32];
2237 SILC_LOG_DEBUG(("Start"));
2239 argc = silc_argument_get_arg_num(cmd->args);
2241 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2242 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2246 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2247 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2251 /* Get Channel ID */
2252 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2254 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2255 SILC_STATUS_ERR_NO_CHANNEL_ID);
2258 id = silc_id_payload_parse_id(tmp, len);
2260 /* Get channel entry */
2261 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2263 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2264 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2268 /* Check whether this client is on the channel */
2269 if (!silc_server_client_on_channel(id_entry, channel)) {
2270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2271 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2275 /* Notify routers that they should remove this client from their list
2276 of clients on the channel. */
2277 if (!server->standalone)
2278 silc_server_send_remove_channel_user(server,
2279 server->id_entry->router->connection,
2280 server->server_type == SILC_ROUTER ?
2281 TRUE : FALSE, id_entry->id, id);
2283 /* Remove client from channel */
2284 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2289 /* If the channel does not exist anymore we won't send anything */
2293 /* Re-generate channel key */
2294 key_len = channel->key_len / 8;
2295 for (i = 0; i < key_len; i++)
2296 channel_key[i] = silc_rng_get_byte(server->rng);
2297 channel->channel_key->cipher->set_key(channel->channel_key->context,
2298 channel_key, key_len);
2299 memset(channel->key, 0, key_len);
2300 silc_free(channel->key);
2301 channel->key = silc_calloc(key_len, sizeof(*channel->key));
2302 memcpy(channel->key, channel_key, key_len);
2303 memset(channel_key, 0, sizeof(channel_key));
2305 /* Encode channel key payload to be distributed on the channel */
2307 silc_channel_key_payload_encode(len, tmp,
2308 strlen(channel->channel_key->cipher->name),
2309 channel->channel_key->cipher->name,
2310 key_len, channel->key);
2312 /* If we are normal server then we will send it to our router. If we
2313 are router we will send it to all local servers that has clients on
2315 if (server->server_type == SILC_SERVER) {
2316 if (!server->standalone)
2317 silc_server_packet_send(server,
2318 cmd->server->id_entry->router->connection,
2319 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2325 /* Send to locally connected clients on the channel */
2326 silc_server_packet_send_local_channel(server, channel,
2327 SILC_PACKET_CHANNEL_KEY, 0,
2328 packet->data, packet->len, FALSE);
2330 silc_buffer_free(packet);
2334 silc_server_command_free(cmd);
2337 /* Server side of command NAMES. Resolves clients and their names currently
2338 joined on the requested channel. The name list is sent back to the
2341 SILC_SERVER_CMD_FUNC(names)
2343 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2344 SilcServer server = cmd->server;
2345 SilcChannelEntry channel;
2346 SilcChannelClientEntry chl;
2349 unsigned int i, len, len2, tmp_len, argc;
2351 char *name_list = NULL, *n;
2352 SilcBuffer client_id_list;
2353 SilcBuffer client_mode_list;
2355 SILC_LOG_DEBUG(("Start"));
2357 argc = silc_argument_get_arg_num(cmd->args);
2359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2360 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2364 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2365 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2369 /* Get Channel ID */
2370 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2373 SILC_STATUS_ERR_NO_CHANNEL_ID);
2376 id = silc_id_payload_parse_id(tmp, tmp_len);
2378 /* Check whether the channel exists. If we are normal server and the
2379 channel does not exist we will send this same command to our router
2380 which will know if the channel exists. */
2381 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2383 if (server->server_type == SILC_SERVER && !server->standalone) {
2384 /* XXX Send names command */
2386 cmd->pending = TRUE;
2387 silc_server_command_pending(SILC_COMMAND_NAMES,
2388 silc_server_command_names, context);
2392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2393 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2397 /* Assemble the name list now */
2400 silc_list_start(channel->user_list);
2402 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2403 n = chl->client->nickname;
2407 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2408 memcpy(name_list + (len - len2), n, len2);
2411 if (i == silc_list_count(channel->user_list) - 1)
2413 memcpy(name_list + len, ",", 1);
2421 /* Assemble the Client ID list now */
2422 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2423 silc_list_count(channel->user_list));
2424 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2425 silc_list_start(channel->user_list);
2426 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2429 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2430 silc_buffer_format(client_id_list,
2431 SILC_STR_UI_XNSTRING(idp->data, idp->len),
2433 silc_buffer_pull(client_id_list, idp->len);
2434 silc_buffer_free(idp);
2436 silc_buffer_push(client_id_list,
2437 client_id_list->data - client_id_list->head);
2439 /* Assemble mode list */
2440 client_mode_list = silc_buffer_alloc(4 *
2441 silc_list_count(channel->user_list));
2442 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2443 silc_list_start(channel->user_list);
2444 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2445 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2446 silc_buffer_pull(client_mode_list, 4);
2448 silc_buffer_push(client_mode_list,
2449 client_mode_list->data - client_mode_list->head);
2452 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2453 SILC_STATUS_OK, 0, 4,
2457 4, client_id_list->data,
2458 client_id_list->len,
2459 5, client_mode_list->data,
2460 client_mode_list->len);
2461 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2462 packet->data, packet->len, FALSE);
2464 silc_buffer_free(packet);
2465 silc_free(name_list);
2466 silc_buffer_free(client_id_list);
2467 silc_buffer_free(client_mode_list);
2471 silc_server_command_free(cmd);