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,
89 SilcIDListData idata = (SilcIDListData)sock->user_data;
90 if (idata->registered)
93 silc_server_command_send_status_reply(cmd, command,
94 SILC_STATUS_ERR_NOT_REGISTERED);
95 silc_server_command_free(cmd);
99 /* Processes received command packet. */
101 void silc_server_command_process(SilcServer server,
102 SilcSocketConnection sock,
103 SilcPacketContext *packet)
105 SilcServerCommandContext ctx;
106 SilcServerCommand *cmd;
109 /* XXX allow commands in but do not execute them more than once per
112 /* Check whether it is allowed for this connection to execute any
114 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
116 SilcClientEntry client = (SilcClientEntry)sock->user_data;
121 /* Allow only one command executed in 2 seconds. */
122 curtime = time(NULL);
123 if (client->last_command && (curtime - client->last_command) < 2)
126 /* Update access time */
127 client->last_command = curtime;
131 /* Allocate command context. This must be free'd by the
132 command routine receiving it. */
133 ctx = silc_calloc(1, sizeof(*ctx));
134 ctx->server = server;
136 ctx->packet = packet; /* Save original packet */
138 /* Parse the command payload in the packet */
139 ctx->payload = silc_command_payload_parse(packet->buffer);
141 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
142 silc_buffer_free(packet->buffer);
146 ctx->args = silc_command_get_args(ctx->payload);
148 /* Execute command. If this fails the packet is dropped. */
149 for (cmd = silc_command_list; cmd->cb; cmd++)
150 if (cmd->cmd == silc_command_get(ctx->payload)) {
152 if (!(cmd->flags & SILC_CF_REG)) {
157 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
164 SILC_LOG_ERROR(("Unknown command, packet dropped"));
170 silc_buffer_free(packet->buffer);
173 /* Add new pending command to the list of pending commands. Currently
174 pending commands are executed from command replies, thus we can
175 execute any command after receiving some specific command reply.
177 The argument `reply_cmd' is the command reply from where the callback
178 function is to be called, thus, it IS NOT the command to be executed. */
180 void silc_server_command_pending(SilcCommand reply_cmd,
181 SilcCommandCb callback,
184 SilcServerCommandPending *reply, *r;
186 reply = silc_calloc(1, sizeof(*reply));
187 reply->reply_cmd = reply_cmd;
188 reply->context = context;
189 reply->callback = callback;
191 if (silc_command_pending == NULL) {
192 silc_command_pending = reply;
196 for (r = silc_command_pending; r; r = r->next) {
197 if (r->next == NULL) {
204 /* Deletes pending command by reply command type. */
206 void silc_server_command_pending_del(SilcCommand reply_cmd)
208 SilcServerCommandPending *r, *tmp;
210 if (silc_command_pending) {
211 if (silc_command_pending->reply_cmd == reply_cmd) {
212 silc_free(silc_command_pending);
213 silc_command_pending = NULL;
217 for (r = silc_command_pending; r; r = r->next) {
218 if (r->next && r->next->reply_cmd == reply_cmd) {
220 r->next = r->next->next;
228 /* Free's the command context allocated before executing the command */
230 static void silc_server_command_free(SilcServerCommandContext cmd)
233 silc_command_free_payload(cmd->payload);
238 /* Sends simple status message as command reply packet */
241 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
243 SilcCommandStatus status)
247 SILC_LOG_DEBUG(("Sending command status %d", status));
249 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
250 silc_server_packet_send(cmd->server, cmd->sock,
251 SILC_PACKET_COMMAND_REPLY, 0,
252 buffer->data, buffer->len, FALSE);
253 silc_buffer_free(buffer);
256 /* Sends command status reply with one extra argument. The argument
257 type must be sent as argument. */
260 silc_server_command_send_status_data(SilcServerCommandContext cmd,
262 SilcCommandStatus status,
263 unsigned int arg_type,
265 unsigned int arg_len)
269 SILC_LOG_DEBUG(("Sending command status %d", status));
271 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
272 arg_type, arg, arg_len);
273 silc_server_packet_send(cmd->server, cmd->sock,
274 SILC_PACKET_COMMAND_REPLY, 0,
275 buffer->data, buffer->len, FALSE);
276 silc_buffer_free(buffer);
279 /* Server side of command WHOIS. Processes user's query and sends found
280 results as command replies back to the client. */
282 SILC_SERVER_CMD_FUNC(whois)
284 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
285 SilcServer server = cmd->server;
286 char *tmp, *nick = NULL, *server_name = NULL;
287 unsigned int i, argc, count = 0, len, clients_count;
289 SilcClientID *client_id = NULL;
290 SilcBuffer packet, idp;
291 SilcClientEntry *clients = NULL, entry;
292 SilcCommandStatus status;
294 SILC_LOG_DEBUG(("Start"));
296 argc = silc_argument_get_arg_num(cmd->args);
298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
299 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
303 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
304 SILC_STATUS_ERR_TOO_MANY_PARAMS);
308 /* If client ID is in the command it must be used instead of nickname */
309 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
312 /* No ID, get the nickname@server string and parse it. */
313 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
315 if (strchr(tmp, '@')) {
316 len = strcspn(tmp, "@");
317 nick = silc_calloc(len + 1, sizeof(char));
318 memcpy(nick, tmp, len);
319 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
320 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
326 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
330 /* Command includes ID, use that */
331 client_id = silc_id_payload_parse_id(tmp, len);
335 /* Get the max count of reply messages allowed */
337 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
340 SILC_STATUS_ERR_TOO_MANY_PARAMS);
344 silc_free(server_name);
350 /* Get all clients matching that nickname */
352 clients = silc_idlist_get_clients_by_nickname(server->local_list,
356 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
358 clients = silc_calloc(1, sizeof(*clients));
366 /* If we are normal server and are connected to a router we will
367 make global query from the router. */
368 if (server->server_type == SILC_SERVER && !server->standalone) {
373 /* If we are router then we will check our global list as well. */
374 if (server->server_type == SILC_ROUTER) {
376 silc_idlist_find_client_by_nickname(server->global_list,
379 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
380 SILC_STATUS_ERR_NO_SUCH_NICK,
381 3, tmp, strlen(tmp));
387 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
388 SILC_STATUS_ERR_NO_SUCH_NICK,
389 3, tmp, strlen(tmp));
395 /* XXX, works only for local server info */
397 status = SILC_STATUS_OK;
398 if (clients_count > 1)
399 status = SILC_STATUS_LIST_START;
401 for (i = 0; i < clients_count; i++) {
404 if (count && i - 1 == count)
407 if (clients_count > 2)
408 status = SILC_STATUS_LIST_ITEM;
410 if (clients_count > 1 && i == clients_count - 1)
411 status = SILC_STATUS_LIST_END;
413 /* Send WHOIS reply */
414 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
415 tmp = silc_argument_get_first_arg(cmd->args, NULL);
418 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
419 char nh[256], uh[256];
420 unsigned char idle[4];
421 SilcSocketConnection hsock;
423 memset(uh, 0, sizeof(uh));
424 memset(nh, 0, sizeof(nh));
426 strncat(nh, entry->nickname, strlen(entry->nickname));
428 len = entry->router ? strlen(entry->router->server_name) :
429 strlen(server->server_name);
430 strncat(nh, entry->router ? entry->router->server_name :
431 server->server_name, len);
433 strncat(uh, entry->username, strlen(entry->username));
435 hsock = (SilcSocketConnection)entry->connection;
436 len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
437 strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
439 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
444 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
446 2, idp->data, idp->len,
450 strlen(entry->userinfo),
454 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
456 2, idp->data, idp->len,
464 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
466 2, idp->data, idp->len,
468 strlen(entry->nickname),
469 4, tmp, strlen(tmp)); /* XXX */
471 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
472 0, packet->data, packet->len, FALSE);
474 silc_buffer_free(packet);
475 silc_buffer_free(idp);
481 silc_free(client_id);
484 silc_server_command_free(cmd);
487 SILC_SERVER_CMD_FUNC(whowas)
491 SILC_SERVER_CMD_FUNC(identify)
493 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
494 SilcServer server = cmd->server;
495 char *tmp, *nick = NULL, *server_name = NULL;
496 unsigned int argc, count = 0, len;
498 SilcClientID *client_id = NULL;
499 SilcClientEntry entry;
500 SilcBuffer packet, idp;
502 SILC_LOG_DEBUG(("Start"));
504 argc = silc_argument_get_arg_num(cmd->args);
506 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
507 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
512 SILC_STATUS_ERR_TOO_MANY_PARAMS);
516 /* If client ID is in the command it must be used instead of nickname */
517 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
520 /* Get the nickname@server string and parse it. */
521 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
523 if (strchr(tmp, '@')) {
524 len = strcspn(tmp, "@");
525 nick = silc_calloc(len + 1, sizeof(char));
526 memcpy(nick, tmp, len);
527 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
528 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
534 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
538 /* Command includes ID, use that */
539 client_id = silc_id_payload_parse_id(tmp, len);
543 /* Get the max count of reply messages allowed */
545 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
547 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
548 SILC_STATUS_ERR_TOO_MANY_PARAMS);
556 entry = silc_idlist_find_client_by_nickname(server->local_list,
559 entry = silc_idlist_find_client_by_hash(server->global_list,
560 nick, server->md5hash);
562 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
565 /* If client was not found and if we are normal server and are connected
566 to a router we will make global query from the router. */
567 if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
569 SilcBuffer buffer = cmd->packet->buffer;
571 SILC_LOG_DEBUG(("Requesting identify from router"));
573 /* Send IDENTIFY command to our router */
574 silc_buffer_push(buffer, buffer->data - buffer->head);
575 silc_server_packet_forward(server, (SilcSocketConnection)
576 server->id_entry->router->connection,
577 buffer->data, buffer->len, TRUE);
581 /* If we are router we have checked our local list by nickname and our
582 global list by hash so far. It is possible that the client is still not
583 found and we'll check it from local list by hash. */
584 if (!entry && server->server_type == SILC_ROUTER)
585 entry = silc_idlist_find_client_by_hash(server->local_list,
586 nick, server->md5hash);
589 /* The client definitely does not exist */
590 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
591 SILC_STATUS_ERR_NO_SUCH_NICK,
592 3, tmp, strlen(tmp));
596 /* Send IDENTIFY reply */
597 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
598 tmp = silc_argument_get_first_arg(cmd->args, NULL);
599 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
600 SILC_STATUS_OK, 0, 2,
601 2, idp->data, idp->len,
602 3, nick, strlen(nick));
603 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
604 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
605 silc_server_packet_send_dest(server, cmd->sock,
606 SILC_PACKET_COMMAND_REPLY, 0,
607 id, cmd->packet->src_id_type,
608 packet->data, packet->len, FALSE);
611 silc_server_packet_send(server, cmd->sock,
612 SILC_PACKET_COMMAND_REPLY, 0,
613 packet->data, packet->len, FALSE);
616 silc_buffer_free(packet);
617 silc_buffer_free(idp);
619 silc_free(client_id);
625 silc_free(server_name);
626 silc_server_command_free(cmd);
629 /* Checks string for bad characters and returns TRUE if they are found. */
631 static int silc_server_command_bad_chars(char *nick)
633 if (strchr(nick, '\\')) return TRUE;
634 if (strchr(nick, '\"')) return TRUE;
635 if (strchr(nick, '´')) return TRUE;
636 if (strchr(nick, '`')) return TRUE;
637 if (strchr(nick, '\'')) return TRUE;
638 if (strchr(nick, '*')) return TRUE;
639 if (strchr(nick, '/')) return TRUE;
640 if (strchr(nick, '@')) return TRUE;
645 /* Server side of command NICK. Sets nickname for user. Setting
646 nickname causes generation of a new client ID for the client. The
647 new client ID is sent to the client after changing the nickname. */
649 SILC_SERVER_CMD_FUNC(nick)
651 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
652 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
653 SilcServer server = cmd->server;
654 SilcBuffer packet, nidp, oidp;
655 SilcClientID *new_id;
658 SILC_LOG_DEBUG(("Start"));
660 /* Check number of arguments */
661 if (silc_argument_get_arg_num(cmd->args) < 1) {
662 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
663 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
668 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
669 if (silc_server_command_bad_chars(nick) == TRUE) {
670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
671 SILC_STATUS_ERR_BAD_NICKNAME);
675 /* Create new Client ID */
676 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
677 cmd->server->md5hash, nick,
680 /* Send notify about nickname change to our router. We send the new
681 ID and ask to replace it with the old one. */
682 if (cmd->server->server_type == SILC_SERVER && !cmd->server->standalone)
683 silc_server_send_replace_id(server, server->id_entry->router->connection,
685 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
686 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
688 /* If we are router we have to distribute the new Client ID to all
690 if (cmd->server->server_type == SILC_ROUTER && !cmd->server->standalone)
691 silc_server_send_replace_id(server, server->id_entry->router->connection,
693 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
694 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
696 /* Remove old cache entry */
697 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
700 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
704 memset(client->id, 0, SILC_ID_CLIENT_LEN);
705 silc_free(client->id);
708 /* Save the nickname as this client is our local client */
709 if (client->nickname)
710 silc_free(client->nickname);
712 client->nickname = strdup(nick);
715 /* Update client cache */
716 silc_idcache_add(server->local_list->clients, client->nickname,
717 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
719 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
721 /* Send NICK_CHANGE notify */
722 silc_server_send_notify_on_channels(server, client,
723 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
724 oidp->data, oidp->len,
725 nidp->data, nidp->len);
727 /* Send the new Client ID as reply command back to client */
728 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
729 SILC_STATUS_OK, 0, 1,
730 2, nidp->data, nidp->len);
731 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
732 0, packet->data, packet->len, FALSE);
734 silc_buffer_free(packet);
735 silc_buffer_free(nidp);
736 silc_buffer_free(oidp);
739 silc_server_command_free(cmd);
742 SILC_SERVER_CMD_FUNC(list)
746 /* Server side of TOPIC command. Sets topic for channel and/or returns
747 current topic to client. */
749 SILC_SERVER_CMD_FUNC(topic)
751 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
752 SilcServer server = cmd->server;
753 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
754 SilcChannelID *channel_id;
755 SilcChannelEntry channel;
756 SilcChannelClientEntry chl;
757 SilcBuffer packet, idp;
759 unsigned int argc, tmp_len;
761 /* Check number of arguments */
762 argc = silc_argument_get_arg_num(cmd->args);
764 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
765 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
770 SILC_STATUS_ERR_TOO_MANY_PARAMS);
775 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
777 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
778 SILC_STATUS_ERR_NO_CHANNEL_ID);
781 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
783 /* Check whether the channel exists */
784 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
786 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
787 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
793 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
796 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
800 if (strlen(tmp) > 256) {
801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
802 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
806 /* See whether has rights to change topic */
807 silc_list_start(channel->user_list);
808 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
809 if (chl->client == client) {
810 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
812 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
820 /* Set the topic for channel */
822 silc_free(channel->topic);
823 channel->topic = strdup(tmp);
825 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
827 /* Send notify about topic change to all clients on the channel */
828 silc_server_send_notify_to_channel(server, channel,
829 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
831 channel->topic, strlen(channel->topic));
832 silc_buffer_free(idp);
835 /* Send the topic to client as reply packet */
836 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
838 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
839 SILC_STATUS_OK, 0, 2,
840 2, idp->data, idp->len,
842 strlen(channel->topic));
844 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
845 SILC_STATUS_OK, 0, 1,
846 2, idp->data, idp->len);
847 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
848 0, packet->data, packet->len, FALSE);
850 silc_buffer_free(packet);
851 silc_buffer_free(idp);
852 silc_free(channel_id);
855 silc_server_command_free(cmd);
858 /* Server side of INVITE command. Invites some client to join some channel. */
860 SILC_SERVER_CMD_FUNC(invite)
862 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
863 SilcServer server = cmd->server;
864 SilcSocketConnection sock = cmd->sock, dest_sock;
865 SilcClientEntry sender, dest;
866 SilcClientID *dest_id;
867 SilcChannelEntry channel;
868 SilcChannelID *channel_id;
871 unsigned int argc, len;
873 /* Check number of arguments */
874 argc = silc_argument_get_arg_num(cmd->args);
876 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
877 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
881 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
882 SILC_STATUS_ERR_TOO_MANY_PARAMS);
886 /* Get destination ID */
887 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
889 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
890 SILC_STATUS_ERR_NO_CLIENT_ID);
893 dest_id = silc_id_payload_parse_id(tmp, len);
896 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
898 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
899 SILC_STATUS_ERR_NO_CHANNEL_ID);
902 channel_id = silc_id_payload_parse_id(tmp, len);
904 /* Check whether the channel exists */
905 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
908 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
912 /* Check whether the sender of this command is on the channel. */
913 sender = (SilcClientEntry)sock->user_data;
914 if (!silc_server_client_on_channel(sender, channel)) {
915 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
916 SILC_STATUS_ERR_NOT_ON_CHANNEL);
920 /* Check whether the channel is invite-only channel. If yes then the
921 sender of this command must be at least channel operator. */
922 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
923 SilcChannelClientEntry chl;
925 silc_list_start(channel->user_list);
926 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
927 if (chl->client == sender) {
928 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
930 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
937 /* Find the connection data for the destination. If it is local we will
938 send it directly otherwise we will send it to router for routing. */
939 dest = silc_idlist_find_client_by_id(server->local_list, dest_id);
941 dest_sock = (SilcSocketConnection)dest->connection;
943 dest_sock = silc_server_get_route(server, dest_id, SILC_ID_CLIENT);
945 /* Check whether the requested client is already on the channel. */
946 /* XXX if we are normal server we don't know about global clients on
947 the channel thus we must request it (NAMES command), check from
948 local cache as well. */
949 if (silc_server_client_on_channel(dest, channel)) {
950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
951 SILC_STATUS_ERR_USER_ON_CHANNEL);
955 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
957 /* Send notify to the client that is invited to the channel */
958 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
959 SILC_NOTIFY_TYPE_INVITE, 2,
960 sidp->data, sidp->len, tmp, len);
962 /* Send command reply */
963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
966 silc_buffer_free(sidp);
969 silc_server_command_free(cmd);
972 /* Quits connection to client. This gets called if client won't
973 close the connection even when it has issued QUIT command. */
975 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
977 SilcServer server = (SilcServer)context;
978 SilcSocketConnection sock = server->sockets[fd];
980 /* Free all client specific data, such as client entry and entires
981 on channels this client may be on. */
982 silc_server_free_sock_user_data(server, sock);
984 /* Close the connection on our side */
985 silc_server_close_connection(server, sock);
988 /* Quits SILC session. This is the normal way to disconnect client. */
990 SILC_SERVER_CMD_FUNC(quit)
992 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
993 SilcServer server = cmd->server;
994 SilcSocketConnection sock = cmd->sock;
996 SILC_LOG_DEBUG(("Start"));
998 /* We quit the connection with little timeout */
999 silc_task_register(server->timeout_queue, sock->sock,
1000 silc_server_command_quit_cb, server,
1001 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1003 silc_server_command_free(cmd);
1006 SILC_SERVER_CMD_FUNC(kill)
1010 /* Server side of command INFO. This sends information about us to
1011 the client. If client requested specific server we will send the
1012 command to that server. */
1014 SILC_SERVER_CMD_FUNC(info)
1016 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1017 SilcServer server = cmd->server;
1018 SilcBuffer packet, idp;
1020 char info_string[256], *dest_server;
1022 argc = silc_argument_get_arg_num(cmd->args);
1024 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1025 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1030 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1034 /* Get server name */
1035 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1038 SILC_STATUS_ERR_NO_SUCH_SERVER);
1042 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1043 /* Send our reply */
1044 memset(info_string, 0, sizeof(info_string));
1045 snprintf(info_string, sizeof(info_string),
1046 "location: %s server: %s admin: %s <%s>",
1047 server->config->admin_info->location,
1048 server->config->admin_info->server_type,
1049 server->config->admin_info->admin_name,
1050 server->config->admin_info->admin_email);
1052 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1054 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1055 SILC_STATUS_OK, 0, 2,
1056 2, idp->data, idp->len,
1058 strlen(info_string));
1059 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1060 packet->data, packet->len, FALSE);
1062 silc_buffer_free(packet);
1063 silc_buffer_free(idp);
1065 /* Send this command to the requested server */
1067 if (server->server_type == SILC_SERVER && !server->standalone) {
1071 if (server->server_type == SILC_ROUTER) {
1077 silc_server_command_free(cmd);
1080 SILC_SERVER_CMD_FUNC(connect)
1084 /* Server side of command PING. This just replies to the ping. */
1086 SILC_SERVER_CMD_FUNC(ping)
1088 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1089 SilcServer server = cmd->server;
1091 unsigned int argc, len;
1094 argc = silc_argument_get_arg_num(cmd->args);
1096 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1097 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1101 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1102 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1107 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1110 SILC_STATUS_ERR_NO_SERVER_ID);
1113 id = silc_id_payload_parse_id(tmp, len);
1115 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1116 /* Send our reply */
1117 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1121 SILC_STATUS_ERR_NO_SUCH_SERVER);
1128 silc_server_command_free(cmd);
1131 SILC_SERVER_CMD_FUNC(oper)
1140 SilcChannelEntry channel;
1142 SilcClientEntry client;
1143 } JoinInternalContext;
1145 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1147 JoinInternalContext *ctx = (JoinInternalContext *)context;
1149 if (ctx->channel->key && ctx->channel->key_len) {
1152 clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1154 silc_server_send_notify_to_channel(ctx->server, ctx->channel,
1155 SILC_NOTIFY_TYPE_JOIN, 1,
1156 clidp->data, clidp->len);
1158 silc_buffer_free(clidp);
1161 silc_task_register(ctx->server->timeout_queue, fd,
1162 silc_server_command_join_notify, context,
1163 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1167 /* Assembles NAMES command and executes it. This is called when client
1168 joins to a channel and we wan't to send NAMES command reply to the
1171 void silc_server_command_send_names(SilcServer server,
1172 SilcSocketConnection sock,
1173 SilcChannelEntry channel)
1175 SilcServerCommandContext cmd;
1176 SilcBuffer buffer, idp;
1178 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1179 buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1180 1, idp->data, idp->len);
1182 cmd = silc_calloc(1, sizeof(*cmd));
1183 cmd->payload = silc_command_payload_parse(buffer);
1184 cmd->args = silc_command_get_args(cmd->payload);
1185 cmd->server = server;
1187 cmd->pending = FALSE;
1189 silc_server_command_names((void *)cmd);
1194 /* Server side of command JOIN. Joins client into requested channel. If
1195 the channel does not exist it will be created. */
1197 SILC_SERVER_CMD_FUNC(join)
1199 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1200 SilcServer server = cmd->server;
1201 SilcSocketConnection sock = cmd->sock;
1202 SilcBuffer buffer = cmd->packet->buffer;
1203 int argc, i, k, tmp_len;
1204 char *tmp, *channel_name = NULL, *cipher = NULL;
1205 unsigned char *passphrase = NULL, mode[4];
1206 unsigned int umode = 0;
1207 SilcChannelEntry channel;
1208 SilcChannelClientEntry chl;
1209 SilcServerID *router_id;
1210 SilcBuffer packet, idp;
1211 SilcClientEntry client;
1213 SILC_LOG_DEBUG(("Start"));
1215 /* Check number of parameters */
1216 argc = silc_argument_get_arg_num(cmd->args);
1218 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1219 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1224 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1228 /* Get channel name */
1229 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1232 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1237 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1239 SILC_STATUS_ERR_BAD_CHANNEL);
1240 silc_free(channel_name);
1244 /* Get passphrase */
1245 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1247 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1248 memcpy(passphrase, tmp, tmp_len);
1251 /* Get cipher name */
1252 cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1254 /* See if the channel exists */
1256 silc_idlist_find_channel_by_name(server->local_list, channel_name);
1258 /* Channel not found */
1260 /* If we are standalone server we don't have a router, we just create
1261 the channel by ourselves. */
1262 if (server->standalone) {
1263 router_id = server->id;
1264 channel = silc_server_new_channel(server, router_id, cipher,
1266 umode |= SILC_CHANNEL_UMODE_CHANOP;
1267 umode |= SILC_CHANNEL_UMODE_CHANFO;
1274 /* No channel ID found, the channel does not exist on our server.
1275 We send JOIN command to our router which will handle the joining
1276 procedure (either creates the channel if it doesn't exist or
1277 joins the client to it) - if we are normal server. */
1278 if (server->server_type == SILC_SERVER) {
1280 /* Forward the original JOIN command to the router */
1281 silc_buffer_push(buffer, buffer->data - buffer->head);
1282 silc_server_packet_forward(server, (SilcSocketConnection)
1283 server->id_entry->router->connection,
1284 buffer->data, buffer->len, TRUE);
1286 /* Add the command to be pending. It will be re-executed after
1287 router has replied back to us. */
1288 cmd->pending = TRUE;
1289 silc_server_command_pending(SILC_COMMAND_JOIN,
1290 silc_server_command_join, context);
1295 /* If we are router and the channel does not exist we will check our
1296 global list for the channel. */
1297 if (!channel && server->server_type == SILC_ROUTER) {
1299 /* Notify all routers about the new channel in SILC network. */
1300 if (!server->standalone) {
1302 silc_server_send_new_id(server, server->id_entry->router->connection,
1304 xxx, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN);
1313 * Check channel modes
1316 /* Check invite list if channel is invite-only channel */
1317 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1318 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1319 /* Invite list is specified. Check whether client is invited in the
1320 list. If not, then check whether it has been invited otherwise. */
1323 /* XXX client must be invited to be able to join the channel */
1327 /* Check ban list if set */
1328 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1332 /* Check the channel passphrase if set. */
1333 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1334 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1335 strlen(channel->mode_data.passphrase))) {
1336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1337 SILC_STATUS_ERR_BAD_PASSWORD);
1342 /* Check user count limit if set. */
1343 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1344 if (silc_list_count(channel->user_list) + 1 >
1345 channel->mode_data.user_limit) {
1346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1347 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1353 * Client is allowed to join to the channel. Make it happen.
1356 /* If the JOIN request was forwarded to us we will make a bit slower
1357 query to get the client pointer. Otherwise, we get the client pointer
1359 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1360 client = (SilcClientEntry)sock->user_data;
1362 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1363 client = silc_idlist_find_client_by_id(server->local_list, id);
1371 /* Check whether the client already is on the channel */
1372 if (silc_server_client_on_channel(client, channel)) {
1373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1374 SILC_STATUS_ERR_USER_ON_CHANNEL);
1378 /* Join the client to the channel by adding it to channel's user list.
1379 Add also the channel to client entry's channels list for fast cross-
1381 chl = silc_calloc(1, sizeof(*chl));
1383 chl->client = client;
1384 chl->channel = channel;
1385 silc_list_add(channel->user_list, chl);
1386 silc_list_add(client->channels, chl);
1388 /* Notify router about new user on channel. If we are normal server
1389 we send it to our router, if we are router we send it to our
1391 if (!server->standalone) {
1395 /* Send command reply to the client. Client receives the Channe ID,
1396 channel mode and possibly other information in this reply packet. */
1397 if (!cmd->pending) {
1398 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1399 SILC_PUT32_MSB(channel->mode, mode);
1401 if (!channel->topic)
1403 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1404 SILC_STATUS_OK, 0, 3,
1406 strlen(channel_name),
1407 3, idp->data, idp->len,
1411 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1412 SILC_STATUS_OK, 0, 4,
1414 strlen(channel_name),
1415 3, idp->data, idp->len,
1418 strlen(channel->topic));
1420 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1421 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1422 silc_server_packet_send_dest(cmd->server, cmd->sock,
1423 SILC_PACKET_COMMAND_REPLY, 0,
1424 id, cmd->packet->src_id_type,
1425 packet->data, packet->len, FALSE);
1428 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1429 packet->data, packet->len, FALSE);
1430 silc_buffer_free(packet);
1432 /* Send channel key to the client. Client cannot start transmitting
1433 to the channel until we have sent the key. */
1434 tmp_len = strlen(channel->channel_key->cipher->name);
1436 silc_channel_key_payload_encode(idp->len, idp->data,
1437 strlen(channel->channel_key->
1439 channel->channel_key->cipher->name,
1440 channel->key_len / 8, channel->key);
1442 silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
1443 packet->data, packet->len, FALSE);
1445 silc_buffer_free(packet);
1446 silc_buffer_free(idp);
1449 /* Finally, send notify message to all clients on the channel about
1450 new user on the channel. */
1451 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1452 if (!cmd->pending) {
1455 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1457 silc_server_send_notify_to_channel(server, channel,
1458 SILC_NOTIFY_TYPE_JOIN, 1,
1459 clidp->data, clidp->len);
1461 silc_buffer_free(clidp);
1463 /* This is pending command request. Send the notify after we have
1464 received the key for the channel from the router. */
1465 JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
1466 ctx->channel_name = channel_name;
1467 ctx->nickname = client->nickname;
1468 ctx->username = client->username;
1469 ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
1470 ctx->channel = channel;
1471 ctx->server = server;
1472 ctx->client = client;
1473 silc_task_register(server->timeout_queue, sock->sock,
1474 silc_server_command_join_notify, ctx,
1475 0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1479 /* Send NAMES command reply to the joined channel so the user sees who
1480 is currently on the channel. */
1481 silc_server_command_send_names(server, sock, channel);
1484 silc_server_command_free(cmd);
1487 /* Server side of command MOTD. Sends server's current "message of the
1488 day" to the client. */
1490 SILC_SERVER_CMD_FUNC(motd)
1492 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1493 SilcServer server = cmd->server;
1498 SILC_LOG_DEBUG(("Start"));
1500 argc = silc_argument_get_arg_num(cmd->args);
1502 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1503 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1508 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1512 /* XXX show currently only our motd */
1514 if (server->config && server->config->motd &&
1515 server->config->motd->motd_file) {
1518 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
1523 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
1529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
1534 silc_server_command_free(cmd);
1537 SILC_SERVER_CMD_FUNC(umode)
1541 /* Checks that client has rights to add or remove channel modes. If any
1542 of the checks fails FALSE is returned. */
1544 int silc_server_check_cmode_rights(SilcChannelEntry channel,
1545 SilcChannelClientEntry client,
1548 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1549 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1551 /* Check whether has rights to change anything */
1552 if (!is_op && !is_fo)
1555 /* Check whether has rights to change everything */
1559 /* We know that client is channel operator, check that they are not
1560 changing anything that requires channel founder rights. Rest of the
1561 modes are available automatically for channel operator. */
1563 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1564 if (is_op && !is_fo)
1567 if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
1568 if (is_op && !is_fo)
1573 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1574 if (is_op && !is_fo)
1577 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1578 if (is_op && !is_fo)
1583 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1584 if (is_op && !is_fo)
1587 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1588 if (is_op && !is_fo)
1596 /* Server side command of CMODE. Changes channel mode */
1598 SILC_SERVER_CMD_FUNC(cmode)
1600 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1601 SilcServer server = cmd->server;
1602 SilcSocketConnection sock = cmd->sock;
1603 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1604 SilcChannelID *channel_id;
1605 SilcClientID *client_id;
1606 SilcChannelEntry channel;
1607 SilcChannelClientEntry chl;
1608 SilcBuffer packet, cidp;
1609 unsigned char *tmp, *tmp_id, *tmp_mask;
1610 unsigned int argc, mode_mask, tmp_len, tmp_len2;
1613 SILC_LOG_DEBUG(("Start"));
1615 argc = silc_argument_get_arg_num(cmd->args);
1617 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1618 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1622 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1623 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1627 /* Get Channel ID */
1628 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
1630 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1631 SILC_STATUS_ERR_NO_CHANNEL_ID);
1634 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
1636 /* Get the channel mode mask */
1637 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1640 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1643 SILC_GET32_MSB(mode_mask, tmp_mask);
1645 /* Get channel entry */
1646 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1648 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1649 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1653 /* Check whether this client is on the channel */
1654 if (!silc_server_client_on_channel(client, channel)) {
1655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1656 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1660 /* Get entry to the channel user list */
1661 silc_list_start(channel->user_list);
1662 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1663 if (chl->client == client)
1666 /* Check that client has rights to change any requested channel modes */
1667 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
1668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1669 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1674 * Check the modes. Modes that requires nothing special operation are
1678 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
1679 /* Channel uses private keys to protect traffic. Client(s) has set the
1680 key locally they want to use, server does not know that key. */
1681 /* Nothing interesting to do here now */
1683 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1684 /* The mode is removed and we need to generate and distribute
1685 new channel key. Clients are not using private channel keys
1686 anymore after this. */
1687 unsigned int key_len;
1688 unsigned char channel_key[32];
1690 /* XXX Duplicated code, make own function for this!! LEAVE uses this
1693 /* Re-generate channel key */
1694 key_len = channel->key_len / 8;
1695 for (i = 0; i < key_len; i++)
1696 channel_key[i] = silc_rng_get_byte(server->rng);
1697 channel->channel_key->cipher->set_key(channel->channel_key->context,
1698 channel_key, key_len);
1699 memset(channel->key, 0, key_len);
1700 silc_free(channel->key);
1701 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1702 memcpy(channel->key, channel_key, key_len);
1703 memset(channel_key, 0, sizeof(channel_key));
1705 /* Encode channel key payload to be distributed on the channel */
1707 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1708 strlen(channel->channel_key->
1710 channel->channel_key->cipher->name,
1711 key_len, channel->key);
1713 /* If we are normal server then we will send it to our router. If we
1714 are router we will send it to all local servers that has clients on
1716 if (server->server_type == SILC_SERVER) {
1717 if (!server->standalone)
1718 silc_server_packet_send(server,
1719 cmd->server->id_entry->router->connection,
1720 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1726 /* Send to locally connected clients on the channel */
1727 silc_server_packet_send_local_channel(server, channel,
1728 SILC_PACKET_CHANNEL_KEY, 0,
1729 packet->data, packet->len, FALSE);
1730 silc_buffer_free(packet);
1734 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
1735 /* User limit is set on channel */
1736 unsigned int user_limit;
1738 /* Get user limit */
1739 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1741 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
1742 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1743 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1747 SILC_GET32_MSB(user_limit, tmp);
1748 channel->mode_data.user_limit = user_limit;
1751 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
1752 /* User limit mode is unset. Remove user limit */
1753 channel->mode_data.user_limit = 0;
1756 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
1757 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1758 /* Passphrase has been set to channel */
1760 /* Get the passphrase */
1761 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1764 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1768 /* Save the passphrase */
1769 channel->mode_data.passphrase = strdup(tmp);
1772 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1773 /* Passphrase mode is unset. remove the passphrase */
1774 if (channel->mode_data.passphrase) {
1775 silc_free(channel->mode_data.passphrase);
1776 channel->mode_data.passphrase = NULL;
1781 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
1782 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
1783 /* Ban list is specified for channel */
1786 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1789 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1793 /* XXX check that channel founder is not banned */
1795 /* Save the ban list */
1796 channel->mode_data.ban_list = strdup(tmp);
1799 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1800 /* Ban mode is unset. Remove the entire ban list */
1801 if (channel->mode_data.ban_list) {
1802 silc_free(channel->mode_data.ban_list);
1803 channel->mode_data.ban_list = NULL;
1808 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
1809 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
1810 /* Invite list is specified for channel */
1812 /* Get invite list */
1813 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1816 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1820 /* Save the invite linst */
1821 channel->mode_data.invite_list = strdup(tmp);
1824 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1825 /* Invite list mode is unset. Remove the entire invite list */
1826 if (channel->mode_data.invite_list) {
1827 silc_free(channel->mode_data.invite_list);
1828 channel->mode_data.invite_list = NULL;
1833 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
1834 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1835 /* Cipher to use protect the traffic */
1836 unsigned int key_len = 128;
1837 unsigned char channel_key[32];
1841 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
1843 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1844 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1848 cp = strchr(tmp, ':');
1854 /* XXX Duplicated code, make own function for this!! */
1856 /* Delete old cipher and allocate the new one */
1857 silc_cipher_free(channel->channel_key);
1858 silc_cipher_alloc(tmp, &channel->channel_key);
1860 /* Re-generate channel key */
1862 if (key_len > sizeof(channel_key))
1863 key_len = sizeof(channel_key);
1865 for (i = 0; i < key_len; i++)
1866 channel_key[i] = silc_rng_get_byte(server->rng);
1867 channel->channel_key->cipher->set_key(channel->channel_key->context,
1868 channel_key, key_len);
1869 memset(channel->key, 0, key_len);
1870 silc_free(channel->key);
1871 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1872 memcpy(channel->key, channel_key, key_len);
1873 memset(channel_key, 0, sizeof(channel_key));
1875 /* Encode channel key payload to be distributed on the channel */
1877 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1878 strlen(channel->channel_key->
1880 channel->channel_key->cipher->name,
1881 key_len, channel->key);
1883 /* If we are normal server then we will send it to our router. If we
1884 are router we will send it to all local servers that has clients on
1886 if (server->server_type == SILC_SERVER) {
1887 if (!server->standalone)
1888 silc_server_packet_send(server,
1889 cmd->server->id_entry->router->connection,
1890 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1896 /* Send to locally connected clients on the channel */
1897 silc_server_packet_send_local_channel(server, channel,
1898 SILC_PACKET_CHANNEL_KEY, 0,
1899 packet->data, packet->len, FALSE);
1900 silc_buffer_free(packet);
1903 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1904 /* Cipher mode is unset. Remove the cipher and revert back to
1906 unsigned int key_len;
1907 unsigned char channel_key[32];
1909 if (channel->mode_data.cipher) {
1910 silc_free(channel->mode_data.cipher);
1911 channel->mode_data.cipher = NULL;
1912 channel->mode_data.key_len = 0;
1915 /* Generate new cipher and key for the channel */
1917 /* XXX Duplicated code, make own function for this!! */
1919 /* Delete old cipher and allocate default one */
1920 silc_cipher_free(channel->channel_key);
1921 if (!channel->cipher)
1922 silc_cipher_alloc("twofish", &channel->channel_key);
1924 silc_cipher_alloc(channel->cipher, &channel->channel_key);
1926 /* Re-generate channel key */
1927 key_len = channel->key_len / 8;
1928 for (i = 0; i < key_len; i++)
1929 channel_key[i] = silc_rng_get_byte(server->rng);
1930 channel->channel_key->cipher->set_key(channel->channel_key->context,
1931 channel_key, key_len);
1932 memset(channel->key, 0, key_len);
1933 silc_free(channel->key);
1934 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1935 memcpy(channel->key, channel_key, key_len);
1936 memset(channel_key, 0, sizeof(channel_key));
1938 /* Encode channel key payload to be distributed on the channel */
1940 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1941 strlen(channel->channel_key->
1943 channel->channel_key->cipher->name,
1944 key_len, channel->key);
1946 /* If we are normal server then we will send it to our router. If we
1947 are router we will send it to all local servers that has clients on
1949 if (server->server_type == SILC_SERVER) {
1950 if (!server->standalone)
1951 silc_server_packet_send(server,
1952 cmd->server->id_entry->router->connection,
1953 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1959 /* Send to locally connected clients on the channel */
1960 silc_server_packet_send_local_channel(server, channel,
1961 SILC_PACKET_CHANNEL_KEY, 0,
1962 packet->data, packet->len, FALSE);
1963 silc_buffer_free(packet);
1967 /* Finally, set the mode */
1968 channel->mode = mode_mask;
1970 /* Send CMODE_CHANGE notify */
1971 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1972 silc_server_send_notify_to_channel(server, channel,
1973 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
1974 cidp->data, cidp->len,
1978 /* Send command reply to sender */
1979 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
1980 SILC_STATUS_OK, 0, 1,
1982 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1983 packet->data, packet->len, FALSE);
1985 silc_buffer_free(packet);
1986 silc_free(channel_id);
1989 silc_server_command_free(cmd);
1992 /* Server side of CUMODE command. Changes client's mode on a channel. */
1994 SILC_SERVER_CMD_FUNC(cumode)
1996 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1997 SilcServer server = cmd->server;
1998 SilcSocketConnection sock = cmd->sock;
1999 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2000 SilcChannelID *channel_id;
2001 SilcClientID *client_id;
2002 SilcChannelEntry channel;
2003 SilcClientEntry target_client;
2004 SilcChannelClientEntry chl;
2005 SilcBuffer packet, idp;
2006 unsigned char *tmp, *tmp_id, *tmp_mask;
2007 unsigned int argc, target_mask, sender_mask, tmp_len;
2008 int i, notify = FALSE;
2010 SILC_LOG_DEBUG(("Start"));
2012 argc = silc_argument_get_arg_num(cmd->args);
2014 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2015 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2019 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2020 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2024 /* Get Channel ID */
2025 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2027 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2028 SILC_STATUS_ERR_NO_CHANNEL_ID);
2031 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2033 /* Get channel entry */
2034 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
2036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2037 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2041 /* Check whether sender is on the channel */
2042 if (!silc_server_client_on_channel(client, channel)) {
2043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2044 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2048 /* Check that client has rights to change other's rights */
2049 silc_list_start(channel->user_list);
2050 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2051 if (chl->client == client) {
2052 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2053 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2054 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2055 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2059 sender_mask = chl->mode;
2064 /* Get the target client's channel mode mask */
2065 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2068 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2071 SILC_GET32_MSB(target_mask, tmp_mask);
2073 /* Get target Client ID */
2074 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2076 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2077 SILC_STATUS_ERR_NO_CHANNEL_ID);
2080 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2082 /* Get target client's entry */
2083 target_client = silc_idlist_find_client_by_id(server->local_list, client_id);
2085 /* XXX If target client is not one of mine send to primary route */
2088 /* Check whether target client is on the channel */
2089 if (!silc_server_client_on_channel(target_client, channel)) {
2090 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2091 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2095 /* Get entry to the channel user list */
2096 silc_list_start(channel->user_list);
2097 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2098 if (chl->client == target_client)
2105 /* If the target client is founder, no one else can change their mode
2107 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2108 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2109 SILC_STATUS_ERR_NOT_YOU);
2113 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2114 /* Cannot promote anyone to channel founder */
2115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2116 SILC_STATUS_ERR_NOT_YOU);
2119 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2120 if (target_client == client) {
2121 /* Remove channel founder rights from itself */
2122 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2125 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2126 SILC_STATUS_ERR_NOT_YOU);
2132 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2133 /* Promote to operator */
2134 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2135 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2139 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2140 /* Demote to normal user */
2141 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2146 /* Send notify to channel, notify only if mode was actually changed. */
2148 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2149 silc_server_send_notify_to_channel(server, channel,
2150 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2151 idp->data, idp->len,
2152 tmp_mask, 4, tmp_id, tmp_len);
2153 silc_buffer_free(idp);
2156 /* Send command reply to sender */
2157 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2158 SILC_STATUS_OK, 0, 2,
2160 3, tmp_id, tmp_len);
2161 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2162 packet->data, packet->len, FALSE);
2164 silc_buffer_free(packet);
2165 silc_free(channel_id);
2166 silc_free(client_id);
2169 silc_server_command_free(cmd);
2172 /* Server side of KICK command. Kicks client out of channel. */
2174 SILC_SERVER_CMD_FUNC(kick)
2176 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2177 SilcServer server = cmd->server;
2178 SilcSocketConnection sock = cmd->sock;
2179 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2183 SILC_SERVER_CMD_FUNC(restart)
2187 SILC_SERVER_CMD_FUNC(close)
2191 SILC_SERVER_CMD_FUNC(die)
2195 SILC_SERVER_CMD_FUNC(silcoper)
2199 /* Server side command of LEAVE. Removes client from a channel. */
2201 SILC_SERVER_CMD_FUNC(leave)
2203 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2204 SilcServer server = cmd->server;
2205 SilcSocketConnection sock = cmd->sock;
2206 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2208 SilcChannelEntry channel;
2210 unsigned int i, argc, key_len, len;
2211 unsigned char *tmp, channel_key[32];
2213 SILC_LOG_DEBUG(("Start"));
2215 argc = silc_argument_get_arg_num(cmd->args);
2217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2218 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2223 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2227 /* Get Channel ID */
2228 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2231 SILC_STATUS_ERR_NO_CHANNEL_ID);
2234 id = silc_id_payload_parse_id(tmp, len);
2236 /* Get channel entry */
2237 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2240 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2244 /* Check whether this client is on the channel */
2245 if (!silc_server_client_on_channel(id_entry, channel)) {
2246 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2247 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2251 /* Notify routers that they should remove this client from their list
2252 of clients on the channel. */
2253 if (!server->standalone)
2254 silc_server_send_remove_channel_user(server,
2255 server->id_entry->router->connection,
2256 server->server_type == SILC_ROUTER ?
2257 TRUE : FALSE, id_entry->id, id);
2259 /* Remove client from channel */
2260 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2265 /* If the channel does not exist anymore we won't send anything */
2269 /* Re-generate channel key */
2270 key_len = channel->key_len / 8;
2271 for (i = 0; i < key_len; i++)
2272 channel_key[i] = silc_rng_get_byte(server->rng);
2273 channel->channel_key->cipher->set_key(channel->channel_key->context,
2274 channel_key, key_len);
2275 memset(channel->key, 0, key_len);
2276 silc_free(channel->key);
2277 channel->key = silc_calloc(key_len, sizeof(*channel->key));
2278 memcpy(channel->key, channel_key, key_len);
2279 memset(channel_key, 0, sizeof(channel_key));
2281 /* Encode channel key payload to be distributed on the channel */
2283 silc_channel_key_payload_encode(len, tmp,
2284 strlen(channel->channel_key->cipher->name),
2285 channel->channel_key->cipher->name,
2286 key_len, channel->key);
2288 /* If we are normal server then we will send it to our router. If we
2289 are router we will send it to all local servers that has clients on
2291 if (server->server_type == SILC_SERVER) {
2292 if (!server->standalone)
2293 silc_server_packet_send(server,
2294 cmd->server->id_entry->router->connection,
2295 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2301 /* Send to locally connected clients on the channel */
2302 silc_server_packet_send_local_channel(server, channel,
2303 SILC_PACKET_CHANNEL_KEY, 0,
2304 packet->data, packet->len, FALSE);
2306 silc_buffer_free(packet);
2310 silc_server_command_free(cmd);
2313 /* Server side of command NAMES. Resolves clients and their names currently
2314 joined on the requested channel. The name list is sent back to the
2317 SILC_SERVER_CMD_FUNC(names)
2319 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2320 SilcServer server = cmd->server;
2321 SilcChannelEntry channel;
2322 SilcChannelClientEntry chl;
2325 unsigned int i, len, len2, tmp_len, argc;
2327 char *name_list = NULL, *n;
2328 SilcBuffer client_id_list;
2329 SilcBuffer client_mode_list;
2331 SILC_LOG_DEBUG(("Start"));
2333 argc = silc_argument_get_arg_num(cmd->args);
2335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2336 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2341 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2345 /* Get Channel ID */
2346 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2348 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2349 SILC_STATUS_ERR_NO_CHANNEL_ID);
2352 id = silc_id_payload_parse_id(tmp, tmp_len);
2354 /* Check whether the channel exists. If we are normal server and the
2355 channel does not exist we will send this same command to our router
2356 which will know if the channel exists. */
2357 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2359 if (server->server_type == SILC_SERVER && !server->standalone) {
2360 /* XXX Send names command */
2362 cmd->pending = TRUE;
2363 silc_server_command_pending(SILC_COMMAND_NAMES,
2364 silc_server_command_names, context);
2368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2369 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2373 /* Assemble the name list now */
2376 silc_list_start(channel->user_list);
2378 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2379 n = chl->client->nickname;
2383 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2384 memcpy(name_list + (len - len2), n, len2);
2387 if (i == silc_list_count(channel->user_list) - 1)
2389 memcpy(name_list + len, ",", 1);
2397 /* Assemble the Client ID list now */
2398 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2399 silc_list_count(channel->user_list));
2400 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2401 silc_list_start(channel->user_list);
2402 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2405 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2406 silc_buffer_format(client_id_list,
2407 SILC_STR_UI_XNSTRING(idp->data, idp->len),
2409 silc_buffer_pull(client_id_list, idp->len);
2410 silc_buffer_free(idp);
2412 silc_buffer_push(client_id_list,
2413 client_id_list->data - client_id_list->head);
2415 /* Assemble mode list */
2416 client_mode_list = silc_buffer_alloc(4 *
2417 silc_list_count(channel->user_list));
2418 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2419 silc_list_start(channel->user_list);
2420 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2421 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2422 silc_buffer_pull(client_mode_list, 4);
2424 silc_buffer_push(client_mode_list,
2425 client_mode_list->data - client_mode_list->head);
2428 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2429 SILC_STATUS_OK, 0, 4,
2433 4, client_id_list->data,
2434 client_id_list->len,
2435 5, client_mode_list->data,
2436 client_mode_list->len);
2437 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2438 packet->data, packet->len, FALSE);
2440 silc_buffer_free(packet);
2441 silc_free(name_list);
2442 silc_buffer_free(client_id_list);
2443 silc_buffer_free(client_mode_list);
2447 silc_server_command_free(cmd);