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);
494 silc_free(client_id);
497 silc_server_command_free(cmd);
500 SILC_SERVER_CMD_FUNC(whowas)
504 SILC_SERVER_CMD_FUNC(identify)
506 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
507 SilcServer server = cmd->server;
508 char *tmp, *nick = NULL, *server_name = NULL;
509 unsigned int argc, count = 0, len;
511 SilcClientID *client_id = NULL;
512 SilcClientEntry entry;
513 SilcBuffer packet, idp;
515 SILC_LOG_DEBUG(("Start"));
517 argc = silc_argument_get_arg_num(cmd->args);
519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
520 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
525 SILC_STATUS_ERR_TOO_MANY_PARAMS);
529 /* If client ID is in the command it must be used instead of nickname */
530 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
533 /* Get the nickname@server string and parse it. */
534 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
536 if (strchr(tmp, '@')) {
537 len = strcspn(tmp, "@");
538 nick = silc_calloc(len + 1, sizeof(char));
539 memcpy(nick, tmp, len);
540 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
541 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
547 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
551 /* Command includes ID, use that */
552 client_id = silc_id_payload_parse_id(tmp, len);
556 /* Get the max count of reply messages allowed */
558 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
561 SILC_STATUS_ERR_TOO_MANY_PARAMS);
569 entry = silc_idlist_find_client_by_nickname(server->local_list,
572 entry = silc_idlist_find_client_by_hash(server->global_list,
573 nick, server->md5hash);
575 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
578 /* If client was not found and if we are normal server and are connected
579 to a router we will make global query from the router. */
580 if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
582 SilcBuffer buffer = cmd->packet->buffer;
584 SILC_LOG_DEBUG(("Requesting identify from router"));
586 /* Send IDENTIFY command to our router */
587 silc_buffer_push(buffer, buffer->data - buffer->head);
588 silc_server_packet_forward(server, (SilcSocketConnection)
589 server->id_entry->router->connection,
590 buffer->data, buffer->len, TRUE);
594 /* If we are router we have checked our local list by nickname and our
595 global list by hash so far. It is possible that the client is still not
596 found and we'll check it from local list by hash. */
597 if (!entry && server->server_type == SILC_ROUTER)
598 entry = silc_idlist_find_client_by_hash(server->local_list,
599 nick, server->md5hash);
602 /* The client definitely does not exist */
603 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
604 SILC_STATUS_ERR_NO_SUCH_NICK,
605 3, tmp, strlen(tmp));
609 /* Send IDENTIFY reply */
610 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
611 tmp = silc_argument_get_first_arg(cmd->args, NULL);
612 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
613 SILC_STATUS_OK, 0, 2,
614 2, idp->data, idp->len,
615 3, nick, strlen(nick));
616 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
617 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
618 silc_server_packet_send_dest(server, cmd->sock,
619 SILC_PACKET_COMMAND_REPLY, 0,
620 id, cmd->packet->src_id_type,
621 packet->data, packet->len, FALSE);
624 silc_server_packet_send(server, cmd->sock,
625 SILC_PACKET_COMMAND_REPLY, 0,
626 packet->data, packet->len, FALSE);
629 silc_buffer_free(packet);
630 silc_buffer_free(idp);
632 silc_free(client_id);
638 silc_free(server_name);
639 silc_server_command_free(cmd);
642 /* Checks string for bad characters and returns TRUE if they are found. */
644 static int silc_server_command_bad_chars(char *nick)
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;
653 if (strchr(nick, '@')) return TRUE;
658 /* Server side of command NICK. Sets nickname for user. Setting
659 nickname causes generation of a new client ID for the client. The
660 new client ID is sent to the client after changing the nickname. */
662 SILC_SERVER_CMD_FUNC(nick)
664 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
665 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
666 SilcServer server = cmd->server;
667 SilcBuffer packet, nidp, oidp;
668 SilcClientID *new_id;
671 SILC_LOG_DEBUG(("Start"));
673 /* Check number of arguments */
674 if (silc_argument_get_arg_num(cmd->args) < 1) {
675 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
676 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
681 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
682 if (silc_server_command_bad_chars(nick) == TRUE) {
683 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
684 SILC_STATUS_ERR_BAD_NICKNAME);
688 /* Create new Client ID */
689 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
690 cmd->server->md5hash, nick,
693 /* Send notify about nickname change to our router. We send the new
694 ID and ask to replace it with the old one. */
695 if (cmd->server->server_type == SILC_SERVER && !cmd->server->standalone)
696 silc_server_send_replace_id(server, server->id_entry->router->connection,
698 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
699 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
701 /* If we are router we have to distribute the new Client ID to all
703 if (cmd->server->server_type == SILC_ROUTER && !cmd->server->standalone)
704 silc_server_send_replace_id(server, server->id_entry->router->connection,
706 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
707 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
709 /* Remove old cache entry */
710 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
713 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
717 memset(client->id, 0, SILC_ID_CLIENT_LEN);
718 silc_free(client->id);
721 /* Save the nickname as this client is our local client */
722 if (client->nickname)
723 silc_free(client->nickname);
725 client->nickname = strdup(nick);
728 /* Update client cache */
729 silc_idcache_add(server->local_list->clients, client->nickname,
730 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
732 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
734 /* Send NICK_CHANGE notify */
735 silc_server_send_notify_on_channels(server, client,
736 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
737 oidp->data, oidp->len,
738 nidp->data, nidp->len);
740 /* Send the new Client ID as reply command back to client */
741 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
742 SILC_STATUS_OK, 0, 1,
743 2, nidp->data, nidp->len);
744 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
745 0, packet->data, packet->len, FALSE);
747 silc_buffer_free(packet);
748 silc_buffer_free(nidp);
749 silc_buffer_free(oidp);
752 silc_server_command_free(cmd);
755 SILC_SERVER_CMD_FUNC(list)
759 /* Server side of TOPIC command. Sets topic for channel and/or returns
760 current topic to client. */
762 SILC_SERVER_CMD_FUNC(topic)
764 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
765 SilcServer server = cmd->server;
766 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
767 SilcChannelID *channel_id;
768 SilcChannelEntry channel;
769 SilcChannelClientEntry chl;
770 SilcBuffer packet, idp;
772 unsigned int argc, tmp_len;
774 /* Check number of arguments */
775 argc = silc_argument_get_arg_num(cmd->args);
777 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
778 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
783 SILC_STATUS_ERR_TOO_MANY_PARAMS);
788 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
791 SILC_STATUS_ERR_NO_CHANNEL_ID);
794 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
796 /* Check whether the channel exists */
797 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
799 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
800 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
806 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
808 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
809 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
813 if (strlen(tmp) > 256) {
814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
815 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
819 /* See whether has rights to change topic */
820 silc_list_start(channel->user_list);
821 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
822 if (chl->client == client) {
823 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
824 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
825 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
833 /* Set the topic for channel */
835 silc_free(channel->topic);
836 channel->topic = strdup(tmp);
838 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
840 /* Send notify about topic change to all clients on the channel */
841 silc_server_send_notify_to_channel(server, channel,
842 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
844 channel->topic, strlen(channel->topic));
845 silc_buffer_free(idp);
848 /* Send the topic to client as reply packet */
849 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
851 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
852 SILC_STATUS_OK, 0, 2,
853 2, idp->data, idp->len,
855 strlen(channel->topic));
857 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
858 SILC_STATUS_OK, 0, 1,
859 2, idp->data, idp->len);
860 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
861 0, packet->data, packet->len, FALSE);
863 silc_buffer_free(packet);
864 silc_buffer_free(idp);
865 silc_free(channel_id);
868 silc_server_command_free(cmd);
871 /* Server side of INVITE command. Invites some client to join some channel. */
873 SILC_SERVER_CMD_FUNC(invite)
875 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
876 SilcServer server = cmd->server;
877 SilcSocketConnection sock = cmd->sock, dest_sock;
878 SilcClientEntry sender, dest;
879 SilcClientID *dest_id;
880 SilcChannelEntry channel;
881 SilcChannelID *channel_id;
884 unsigned int argc, len;
886 /* Check number of arguments */
887 argc = silc_argument_get_arg_num(cmd->args);
889 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
890 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
894 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
895 SILC_STATUS_ERR_TOO_MANY_PARAMS);
899 /* Get destination ID */
900 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
902 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
903 SILC_STATUS_ERR_NO_CLIENT_ID);
906 dest_id = silc_id_payload_parse_id(tmp, len);
909 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
912 SILC_STATUS_ERR_NO_CHANNEL_ID);
915 channel_id = silc_id_payload_parse_id(tmp, len);
917 /* Check whether the channel exists */
918 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
920 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
921 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
925 /* Check whether the sender of this command is on the channel. */
926 sender = (SilcClientEntry)sock->user_data;
927 if (!silc_server_client_on_channel(sender, channel)) {
928 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
929 SILC_STATUS_ERR_NOT_ON_CHANNEL);
933 /* Check whether the channel is invite-only channel. If yes then the
934 sender of this command must be at least channel operator. */
935 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
936 SilcChannelClientEntry chl;
938 silc_list_start(channel->user_list);
939 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
940 if (chl->client == sender) {
941 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
942 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
943 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
950 /* Find the connection data for the destination. If it is local we will
951 send it directly otherwise we will send it to router for routing. */
952 dest = silc_idlist_find_client_by_id(server->local_list, dest_id);
954 dest_sock = (SilcSocketConnection)dest->connection;
956 dest_sock = silc_server_get_route(server, dest_id, SILC_ID_CLIENT);
958 /* Check whether the requested client is already on the channel. */
959 /* XXX if we are normal server we don't know about global clients on
960 the channel thus we must request it (NAMES command), check from
961 local cache as well. */
962 if (silc_server_client_on_channel(dest, channel)) {
963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
964 SILC_STATUS_ERR_USER_ON_CHANNEL);
968 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
970 /* Send notify to the client that is invited to the channel */
971 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
972 SILC_NOTIFY_TYPE_INVITE, 2,
973 sidp->data, sidp->len, tmp, len);
975 /* Send command reply */
976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
979 silc_buffer_free(sidp);
982 silc_server_command_free(cmd);
985 /* Quits connection to client. This gets called if client won't
986 close the connection even when it has issued QUIT command. */
988 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
990 SilcServer server = (SilcServer)context;
991 SilcSocketConnection sock = server->sockets[fd];
993 /* Free all client specific data, such as client entry and entires
994 on channels this client may be on. */
995 silc_server_free_sock_user_data(server, sock);
997 /* Close the connection on our side */
998 silc_server_close_connection(server, sock);
1001 /* Quits SILC session. This is the normal way to disconnect client. */
1003 SILC_SERVER_CMD_FUNC(quit)
1005 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1006 SilcServer server = cmd->server;
1007 SilcSocketConnection sock = cmd->sock;
1009 SILC_LOG_DEBUG(("Start"));
1011 /* We quit the connection with little timeout */
1012 silc_task_register(server->timeout_queue, sock->sock,
1013 silc_server_command_quit_cb, server,
1014 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1016 silc_server_command_free(cmd);
1019 SILC_SERVER_CMD_FUNC(kill)
1023 /* Server side of command INFO. This sends information about us to
1024 the client. If client requested specific server we will send the
1025 command to that server. */
1027 SILC_SERVER_CMD_FUNC(info)
1029 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1030 SilcServer server = cmd->server;
1031 SilcBuffer packet, idp;
1033 char info_string[256], *dest_server;
1035 argc = silc_argument_get_arg_num(cmd->args);
1037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1038 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1043 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1047 /* Get server name */
1048 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1051 SILC_STATUS_ERR_NO_SUCH_SERVER);
1055 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1056 /* Send our reply */
1057 memset(info_string, 0, sizeof(info_string));
1058 snprintf(info_string, sizeof(info_string),
1059 "location: %s server: %s admin: %s <%s>",
1060 server->config->admin_info->location,
1061 server->config->admin_info->server_type,
1062 server->config->admin_info->admin_name,
1063 server->config->admin_info->admin_email);
1065 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1067 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1068 SILC_STATUS_OK, 0, 2,
1069 2, idp->data, idp->len,
1071 strlen(info_string));
1072 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1073 packet->data, packet->len, FALSE);
1075 silc_buffer_free(packet);
1076 silc_buffer_free(idp);
1078 /* Send this command to the requested server */
1080 if (server->server_type == SILC_SERVER && !server->standalone) {
1084 if (server->server_type == SILC_ROUTER) {
1090 silc_server_command_free(cmd);
1093 SILC_SERVER_CMD_FUNC(connect)
1097 /* Server side of command PING. This just replies to the ping. */
1099 SILC_SERVER_CMD_FUNC(ping)
1101 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1102 SilcServer server = cmd->server;
1104 unsigned int argc, len;
1107 argc = silc_argument_get_arg_num(cmd->args);
1109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1110 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1114 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1115 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1120 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1122 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1123 SILC_STATUS_ERR_NO_SERVER_ID);
1126 id = silc_id_payload_parse_id(tmp, len);
1128 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1129 /* Send our reply */
1130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1134 SILC_STATUS_ERR_NO_SUCH_SERVER);
1141 silc_server_command_free(cmd);
1144 SILC_SERVER_CMD_FUNC(oper)
1153 SilcChannelEntry channel;
1155 SilcClientEntry client;
1156 } JoinInternalContext;
1158 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1160 JoinInternalContext *ctx = (JoinInternalContext *)context;
1162 if (ctx->channel->key && ctx->channel->key_len) {
1165 clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1167 silc_server_send_notify_to_channel(ctx->server, ctx->channel,
1168 SILC_NOTIFY_TYPE_JOIN, 1,
1169 clidp->data, clidp->len);
1171 silc_buffer_free(clidp);
1174 silc_task_register(ctx->server->timeout_queue, fd,
1175 silc_server_command_join_notify, context,
1176 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1180 /* Assembles NAMES command and executes it. This is called when client
1181 joins to a channel and we wan't to send NAMES command reply to the
1184 void silc_server_command_send_names(SilcServer server,
1185 SilcSocketConnection sock,
1186 SilcChannelEntry channel)
1188 SilcServerCommandContext cmd;
1189 SilcBuffer buffer, idp;
1191 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1192 buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1193 1, idp->data, idp->len);
1195 cmd = silc_calloc(1, sizeof(*cmd));
1196 cmd->payload = silc_command_payload_parse(buffer);
1197 cmd->args = silc_command_get_args(cmd->payload);
1198 cmd->server = server;
1200 cmd->pending = FALSE;
1202 silc_server_command_names((void *)cmd);
1207 /* Server side of command JOIN. Joins client into requested channel. If
1208 the channel does not exist it will be created. */
1210 SILC_SERVER_CMD_FUNC(join)
1212 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1213 SilcServer server = cmd->server;
1214 SilcSocketConnection sock = cmd->sock;
1215 SilcBuffer buffer = cmd->packet->buffer;
1216 int argc, i, k, tmp_len;
1217 char *tmp, *channel_name = NULL, *cipher = NULL;
1218 unsigned char *passphrase = NULL, mode[4];
1219 unsigned int umode = 0;
1220 SilcChannelEntry channel;
1221 SilcChannelClientEntry chl;
1222 SilcServerID *router_id;
1223 SilcBuffer packet, idp;
1224 SilcClientEntry client;
1226 SILC_LOG_DEBUG(("Start"));
1228 /* Check number of parameters */
1229 argc = silc_argument_get_arg_num(cmd->args);
1231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1232 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1236 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1237 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1241 /* Get channel name */
1242 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1245 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1250 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1251 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1252 SILC_STATUS_ERR_BAD_CHANNEL);
1253 silc_free(channel_name);
1257 /* Get passphrase */
1258 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1260 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1261 memcpy(passphrase, tmp, tmp_len);
1264 /* Get cipher name */
1265 cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1267 /* See if the channel exists */
1269 silc_idlist_find_channel_by_name(server->local_list, channel_name);
1271 /* Channel not found */
1273 /* If we are standalone server we don't have a router, we just create
1274 the channel by ourselves. */
1275 if (server->standalone) {
1276 router_id = server->id;
1277 channel = silc_server_new_channel(server, router_id, cipher,
1279 umode |= SILC_CHANNEL_UMODE_CHANOP;
1280 umode |= SILC_CHANNEL_UMODE_CHANFO;
1287 /* No channel ID found, the channel does not exist on our server.
1288 We send JOIN command to our router which will handle the joining
1289 procedure (either creates the channel if it doesn't exist or
1290 joins the client to it) - if we are normal server. */
1291 if (server->server_type == SILC_SERVER) {
1293 /* Forward the original JOIN command to the router */
1294 silc_buffer_push(buffer, buffer->data - buffer->head);
1295 silc_server_packet_forward(server, (SilcSocketConnection)
1296 server->id_entry->router->connection,
1297 buffer->data, buffer->len, TRUE);
1299 /* Add the command to be pending. It will be re-executed after
1300 router has replied back to us. */
1301 cmd->pending = TRUE;
1302 silc_server_command_pending(SILC_COMMAND_JOIN,
1303 silc_server_command_join, context);
1308 /* If we are router and the channel does not exist we will check our
1309 global list for the channel. */
1310 if (!channel && server->server_type == SILC_ROUTER) {
1312 /* Notify all routers about the new channel in SILC network. */
1313 if (!server->standalone) {
1315 silc_server_send_new_id(server, server->id_entry->router->connection,
1317 xxx, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN);
1326 * Check channel modes
1329 /* Check invite list if channel is invite-only channel */
1330 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1331 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1332 /* Invite list is specified. Check whether client is invited in the
1333 list. If not, then check whether it has been invited otherwise. */
1336 /* XXX client must be invited to be able to join the channel */
1340 /* Check ban list if set */
1341 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1345 /* Check the channel passphrase if set. */
1346 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1347 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1348 strlen(channel->mode_data.passphrase))) {
1349 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1350 SILC_STATUS_ERR_BAD_PASSWORD);
1355 /* Check user count limit if set. */
1356 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1357 if (silc_list_count(channel->user_list) + 1 >
1358 channel->mode_data.user_limit) {
1359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1360 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1366 * Client is allowed to join to the channel. Make it happen.
1369 /* If the JOIN request was forwarded to us we will make a bit slower
1370 query to get the client pointer. Otherwise, we get the client pointer
1372 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1373 client = (SilcClientEntry)sock->user_data;
1375 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1376 client = silc_idlist_find_client_by_id(server->local_list, id);
1384 /* Check whether the client already is on the channel */
1385 if (silc_server_client_on_channel(client, channel)) {
1386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1387 SILC_STATUS_ERR_USER_ON_CHANNEL);
1391 /* Join the client to the channel by adding it to channel's user list.
1392 Add also the channel to client entry's channels list for fast cross-
1394 chl = silc_calloc(1, sizeof(*chl));
1396 chl->client = client;
1397 chl->channel = channel;
1398 silc_list_add(channel->user_list, chl);
1399 silc_list_add(client->channels, chl);
1401 /* Notify router about new user on channel. If we are normal server
1402 we send it to our router, if we are router we send it to our
1404 if (!server->standalone) {
1408 /* Send command reply to the client. Client receives the Channe ID,
1409 channel mode and possibly other information in this reply packet. */
1410 if (!cmd->pending) {
1411 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1412 SILC_PUT32_MSB(channel->mode, mode);
1414 if (!channel->topic)
1416 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1417 SILC_STATUS_OK, 0, 3,
1419 strlen(channel_name),
1420 3, idp->data, idp->len,
1424 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1425 SILC_STATUS_OK, 0, 4,
1427 strlen(channel_name),
1428 3, idp->data, idp->len,
1431 strlen(channel->topic));
1433 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1434 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1435 silc_server_packet_send_dest(cmd->server, cmd->sock,
1436 SILC_PACKET_COMMAND_REPLY, 0,
1437 id, cmd->packet->src_id_type,
1438 packet->data, packet->len, FALSE);
1441 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1442 packet->data, packet->len, FALSE);
1443 silc_buffer_free(packet);
1445 /* Send channel key to the client. Client cannot start transmitting
1446 to the channel until we have sent the key. */
1447 tmp_len = strlen(channel->channel_key->cipher->name);
1449 silc_channel_key_payload_encode(idp->len, idp->data,
1450 strlen(channel->channel_key->
1452 channel->channel_key->cipher->name,
1453 channel->key_len / 8, channel->key);
1455 silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
1456 packet->data, packet->len, FALSE);
1458 silc_buffer_free(packet);
1459 silc_buffer_free(idp);
1462 /* Finally, send notify message to all clients on the channel about
1463 new user on the channel. */
1464 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1465 if (!cmd->pending) {
1468 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1470 silc_server_send_notify_to_channel(server, channel,
1471 SILC_NOTIFY_TYPE_JOIN, 1,
1472 clidp->data, clidp->len);
1474 silc_buffer_free(clidp);
1476 /* This is pending command request. Send the notify after we have
1477 received the key for the channel from the router. */
1478 JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
1479 ctx->channel_name = channel_name;
1480 ctx->nickname = client->nickname;
1481 ctx->username = client->username;
1482 ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
1483 ctx->channel = channel;
1484 ctx->server = server;
1485 ctx->client = client;
1486 silc_task_register(server->timeout_queue, sock->sock,
1487 silc_server_command_join_notify, ctx,
1488 0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1492 /* Send NAMES command reply to the joined channel so the user sees who
1493 is currently on the channel. */
1494 silc_server_command_send_names(server, sock, channel);
1497 silc_server_command_free(cmd);
1500 /* Server side of command MOTD. Sends server's current "message of the
1501 day" to the client. */
1503 SILC_SERVER_CMD_FUNC(motd)
1505 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1506 SilcServer server = cmd->server;
1511 SILC_LOG_DEBUG(("Start"));
1513 argc = silc_argument_get_arg_num(cmd->args);
1515 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1516 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1521 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1525 /* XXX show currently only our motd */
1527 if (server->config && server->config->motd &&
1528 server->config->motd->motd_file) {
1531 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
1536 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
1542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
1547 silc_server_command_free(cmd);
1550 SILC_SERVER_CMD_FUNC(umode)
1554 /* Checks that client has rights to add or remove channel modes. If any
1555 of the checks fails FALSE is returned. */
1557 int silc_server_check_cmode_rights(SilcChannelEntry channel,
1558 SilcChannelClientEntry client,
1561 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1562 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1564 /* Check whether has rights to change anything */
1565 if (!is_op && !is_fo)
1568 /* Check whether has rights to change everything */
1572 /* We know that client is channel operator, check that they are not
1573 changing anything that requires channel founder rights. Rest of the
1574 modes are available automatically for channel operator. */
1576 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1577 if (is_op && !is_fo)
1580 if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
1581 if (is_op && !is_fo)
1586 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1587 if (is_op && !is_fo)
1590 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1591 if (is_op && !is_fo)
1596 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1597 if (is_op && !is_fo)
1600 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1601 if (is_op && !is_fo)
1609 /* Server side command of CMODE. Changes channel mode */
1611 SILC_SERVER_CMD_FUNC(cmode)
1613 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1614 SilcServer server = cmd->server;
1615 SilcSocketConnection sock = cmd->sock;
1616 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1617 SilcChannelID *channel_id;
1618 SilcClientID *client_id;
1619 SilcChannelEntry channel;
1620 SilcChannelClientEntry chl;
1621 SilcBuffer packet, cidp;
1622 unsigned char *tmp, *tmp_id, *tmp_mask;
1623 unsigned int argc, mode_mask, tmp_len, tmp_len2;
1626 SILC_LOG_DEBUG(("Start"));
1628 argc = silc_argument_get_arg_num(cmd->args);
1630 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1631 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1635 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1636 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1640 /* Get Channel ID */
1641 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
1643 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1644 SILC_STATUS_ERR_NO_CHANNEL_ID);
1647 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
1649 /* Get the channel mode mask */
1650 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1653 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1656 SILC_GET32_MSB(mode_mask, tmp_mask);
1658 /* Get channel entry */
1659 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1661 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1662 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1666 /* Check whether this client is on the channel */
1667 if (!silc_server_client_on_channel(client, channel)) {
1668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1669 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1673 /* Get entry to the channel user list */
1674 silc_list_start(channel->user_list);
1675 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1676 if (chl->client == client)
1679 /* Check that client has rights to change any requested channel modes */
1680 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
1681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1682 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1687 * Check the modes. Modes that requires nothing special operation are
1691 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
1692 /* Channel uses private keys to protect traffic. Client(s) has set the
1693 key locally they want to use, server does not know that key. */
1694 /* Nothing interesting to do here now */
1696 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1697 /* The mode is removed and we need to generate and distribute
1698 new channel key. Clients are not using private channel keys
1699 anymore after this. */
1700 unsigned int key_len;
1701 unsigned char channel_key[32];
1703 /* XXX Duplicated code, make own function for this!! LEAVE uses this
1706 /* Re-generate channel key */
1707 key_len = channel->key_len / 8;
1708 for (i = 0; i < key_len; i++)
1709 channel_key[i] = silc_rng_get_byte(server->rng);
1710 channel->channel_key->cipher->set_key(channel->channel_key->context,
1711 channel_key, key_len);
1712 memset(channel->key, 0, key_len);
1713 silc_free(channel->key);
1714 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1715 memcpy(channel->key, channel_key, key_len);
1716 memset(channel_key, 0, sizeof(channel_key));
1718 /* Encode channel key payload to be distributed on the channel */
1720 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1721 strlen(channel->channel_key->
1723 channel->channel_key->cipher->name,
1724 key_len, channel->key);
1726 /* If we are normal server then we will send it to our router. If we
1727 are router we will send it to all local servers that has clients on
1729 if (server->server_type == SILC_SERVER) {
1730 if (!server->standalone)
1731 silc_server_packet_send(server,
1732 cmd->server->id_entry->router->connection,
1733 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1739 /* Send to locally connected clients on the channel */
1740 silc_server_packet_send_local_channel(server, channel,
1741 SILC_PACKET_CHANNEL_KEY, 0,
1742 packet->data, packet->len, FALSE);
1743 silc_buffer_free(packet);
1747 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
1748 /* User limit is set on channel */
1749 unsigned int user_limit;
1751 /* Get user limit */
1752 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1754 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
1755 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1756 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1760 SILC_GET32_MSB(user_limit, tmp);
1761 channel->mode_data.user_limit = user_limit;
1764 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
1765 /* User limit mode is unset. Remove user limit */
1766 channel->mode_data.user_limit = 0;
1769 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
1770 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1771 /* Passphrase has been set to channel */
1773 /* Get the passphrase */
1774 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1776 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1777 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1781 /* Save the passphrase */
1782 channel->mode_data.passphrase = strdup(tmp);
1785 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1786 /* Passphrase mode is unset. remove the passphrase */
1787 if (channel->mode_data.passphrase) {
1788 silc_free(channel->mode_data.passphrase);
1789 channel->mode_data.passphrase = NULL;
1794 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
1795 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
1796 /* Ban list is specified for channel */
1799 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1802 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1806 /* XXX check that channel founder is not banned */
1808 /* Save the ban list */
1809 channel->mode_data.ban_list = strdup(tmp);
1812 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1813 /* Ban mode is unset. Remove the entire ban list */
1814 if (channel->mode_data.ban_list) {
1815 silc_free(channel->mode_data.ban_list);
1816 channel->mode_data.ban_list = NULL;
1821 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
1822 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
1823 /* Invite list is specified for channel */
1825 /* Get invite list */
1826 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1829 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1833 /* Save the invite linst */
1834 channel->mode_data.invite_list = strdup(tmp);
1837 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1838 /* Invite list mode is unset. Remove the entire invite list */
1839 if (channel->mode_data.invite_list) {
1840 silc_free(channel->mode_data.invite_list);
1841 channel->mode_data.invite_list = NULL;
1846 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
1847 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1848 /* Cipher to use protect the traffic */
1849 unsigned int key_len = 128;
1850 unsigned char channel_key[32];
1854 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
1856 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1857 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1861 cp = strchr(tmp, ':');
1867 /* XXX Duplicated code, make own function for this!! */
1869 /* Delete old cipher and allocate the new one */
1870 silc_cipher_free(channel->channel_key);
1871 silc_cipher_alloc(tmp, &channel->channel_key);
1873 /* Re-generate channel key */
1875 if (key_len > sizeof(channel_key))
1876 key_len = sizeof(channel_key);
1878 for (i = 0; i < key_len; i++)
1879 channel_key[i] = silc_rng_get_byte(server->rng);
1880 channel->channel_key->cipher->set_key(channel->channel_key->context,
1881 channel_key, key_len);
1882 memset(channel->key, 0, key_len);
1883 silc_free(channel->key);
1884 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1885 memcpy(channel->key, channel_key, key_len);
1886 memset(channel_key, 0, sizeof(channel_key));
1888 /* Encode channel key payload to be distributed on the channel */
1890 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1891 strlen(channel->channel_key->
1893 channel->channel_key->cipher->name,
1894 key_len, channel->key);
1896 /* If we are normal server then we will send it to our router. If we
1897 are router we will send it to all local servers that has clients on
1899 if (server->server_type == SILC_SERVER) {
1900 if (!server->standalone)
1901 silc_server_packet_send(server,
1902 cmd->server->id_entry->router->connection,
1903 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1909 /* Send to locally connected clients on the channel */
1910 silc_server_packet_send_local_channel(server, channel,
1911 SILC_PACKET_CHANNEL_KEY, 0,
1912 packet->data, packet->len, FALSE);
1913 silc_buffer_free(packet);
1916 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1917 /* Cipher mode is unset. Remove the cipher and revert back to
1919 unsigned int key_len;
1920 unsigned char channel_key[32];
1922 if (channel->mode_data.cipher) {
1923 silc_free(channel->mode_data.cipher);
1924 channel->mode_data.cipher = NULL;
1925 channel->mode_data.key_len = 0;
1928 /* Generate new cipher and key for the channel */
1930 /* XXX Duplicated code, make own function for this!! */
1932 /* Delete old cipher and allocate default one */
1933 silc_cipher_free(channel->channel_key);
1934 if (!channel->cipher)
1935 silc_cipher_alloc("twofish", &channel->channel_key);
1937 silc_cipher_alloc(channel->cipher, &channel->channel_key);
1939 /* Re-generate channel key */
1940 key_len = channel->key_len / 8;
1941 for (i = 0; i < key_len; i++)
1942 channel_key[i] = silc_rng_get_byte(server->rng);
1943 channel->channel_key->cipher->set_key(channel->channel_key->context,
1944 channel_key, key_len);
1945 memset(channel->key, 0, key_len);
1946 silc_free(channel->key);
1947 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1948 memcpy(channel->key, channel_key, key_len);
1949 memset(channel_key, 0, sizeof(channel_key));
1951 /* Encode channel key payload to be distributed on the channel */
1953 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1954 strlen(channel->channel_key->
1956 channel->channel_key->cipher->name,
1957 key_len, channel->key);
1959 /* If we are normal server then we will send it to our router. If we
1960 are router we will send it to all local servers that has clients on
1962 if (server->server_type == SILC_SERVER) {
1963 if (!server->standalone)
1964 silc_server_packet_send(server,
1965 cmd->server->id_entry->router->connection,
1966 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1972 /* Send to locally connected clients on the channel */
1973 silc_server_packet_send_local_channel(server, channel,
1974 SILC_PACKET_CHANNEL_KEY, 0,
1975 packet->data, packet->len, FALSE);
1976 silc_buffer_free(packet);
1980 /* Finally, set the mode */
1981 channel->mode = mode_mask;
1983 /* Send CMODE_CHANGE notify */
1984 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1985 silc_server_send_notify_to_channel(server, channel,
1986 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
1987 cidp->data, cidp->len,
1991 /* Send command reply to sender */
1992 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
1993 SILC_STATUS_OK, 0, 1,
1995 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1996 packet->data, packet->len, FALSE);
1998 silc_buffer_free(packet);
1999 silc_free(channel_id);
2002 silc_server_command_free(cmd);
2005 /* Server side of CUMODE command. Changes client's mode on a channel. */
2007 SILC_SERVER_CMD_FUNC(cumode)
2009 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2010 SilcServer server = cmd->server;
2011 SilcSocketConnection sock = cmd->sock;
2012 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2013 SilcChannelID *channel_id;
2014 SilcClientID *client_id;
2015 SilcChannelEntry channel;
2016 SilcClientEntry target_client;
2017 SilcChannelClientEntry chl;
2018 SilcBuffer packet, idp;
2019 unsigned char *tmp, *tmp_id, *tmp_mask;
2020 unsigned int argc, target_mask, sender_mask, tmp_len;
2021 int i, notify = FALSE;
2023 SILC_LOG_DEBUG(("Start"));
2025 argc = silc_argument_get_arg_num(cmd->args);
2027 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2028 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2033 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2037 /* Get Channel ID */
2038 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2040 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2041 SILC_STATUS_ERR_NO_CHANNEL_ID);
2044 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2046 /* Get channel entry */
2047 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
2049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2050 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2054 /* Check whether sender is on the channel */
2055 if (!silc_server_client_on_channel(client, channel)) {
2056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2057 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2061 /* Check that client has rights to change other's rights */
2062 silc_list_start(channel->user_list);
2063 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2064 if (chl->client == client) {
2065 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2066 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2068 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2072 sender_mask = chl->mode;
2077 /* Get the target client's channel mode mask */
2078 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2080 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2081 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2084 SILC_GET32_MSB(target_mask, tmp_mask);
2086 /* Get target Client ID */
2087 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2089 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2090 SILC_STATUS_ERR_NO_CHANNEL_ID);
2093 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2095 /* Get target client's entry */
2096 target_client = silc_idlist_find_client_by_id(server->local_list, client_id);
2098 /* XXX If target client is not one of mine send to primary route */
2101 /* Check whether target client is on the channel */
2102 if (!silc_server_client_on_channel(target_client, channel)) {
2103 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2104 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2108 /* Get entry to the channel user list */
2109 silc_list_start(channel->user_list);
2110 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2111 if (chl->client == target_client)
2118 /* If the target client is founder, no one else can change their mode
2120 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2122 SILC_STATUS_ERR_NOT_YOU);
2126 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2127 /* Cannot promote anyone to channel founder */
2128 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2129 SILC_STATUS_ERR_NOT_YOU);
2132 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2133 if (target_client == client) {
2134 /* Remove channel founder rights from itself */
2135 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2139 SILC_STATUS_ERR_NOT_YOU);
2145 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2146 /* Promote to operator */
2147 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2148 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2152 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2153 /* Demote to normal user */
2154 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2159 /* Send notify to channel, notify only if mode was actually changed. */
2161 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2162 silc_server_send_notify_to_channel(server, channel,
2163 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2164 idp->data, idp->len,
2165 tmp_mask, 4, tmp_id, tmp_len);
2166 silc_buffer_free(idp);
2169 /* Send command reply to sender */
2170 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2171 SILC_STATUS_OK, 0, 2,
2173 3, tmp_id, tmp_len);
2174 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2175 packet->data, packet->len, FALSE);
2177 silc_buffer_free(packet);
2178 silc_free(channel_id);
2179 silc_free(client_id);
2182 silc_server_command_free(cmd);
2185 /* Server side of KICK command. Kicks client out of channel. */
2187 SILC_SERVER_CMD_FUNC(kick)
2189 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2190 SilcServer server = cmd->server;
2191 SilcSocketConnection sock = cmd->sock;
2192 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2196 SILC_SERVER_CMD_FUNC(restart)
2200 SILC_SERVER_CMD_FUNC(close)
2204 SILC_SERVER_CMD_FUNC(die)
2208 SILC_SERVER_CMD_FUNC(silcoper)
2212 /* Server side command of LEAVE. Removes client from a channel. */
2214 SILC_SERVER_CMD_FUNC(leave)
2216 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2217 SilcServer server = cmd->server;
2218 SilcSocketConnection sock = cmd->sock;
2219 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2221 SilcChannelEntry channel;
2223 unsigned int i, argc, key_len, len;
2224 unsigned char *tmp, channel_key[32];
2226 SILC_LOG_DEBUG(("Start"));
2228 argc = silc_argument_get_arg_num(cmd->args);
2230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2231 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2235 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2236 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2240 /* Get Channel ID */
2241 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2244 SILC_STATUS_ERR_NO_CHANNEL_ID);
2247 id = silc_id_payload_parse_id(tmp, len);
2249 /* Get channel entry */
2250 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2253 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2257 /* Check whether this client is on the channel */
2258 if (!silc_server_client_on_channel(id_entry, channel)) {
2259 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2260 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2264 /* Notify routers that they should remove this client from their list
2265 of clients on the channel. */
2266 if (!server->standalone)
2267 silc_server_send_remove_channel_user(server,
2268 server->id_entry->router->connection,
2269 server->server_type == SILC_ROUTER ?
2270 TRUE : FALSE, id_entry->id, id);
2272 /* Remove client from channel */
2273 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2278 /* If the channel does not exist anymore we won't send anything */
2282 /* Re-generate channel key */
2283 key_len = channel->key_len / 8;
2284 for (i = 0; i < key_len; i++)
2285 channel_key[i] = silc_rng_get_byte(server->rng);
2286 channel->channel_key->cipher->set_key(channel->channel_key->context,
2287 channel_key, key_len);
2288 memset(channel->key, 0, key_len);
2289 silc_free(channel->key);
2290 channel->key = silc_calloc(key_len, sizeof(*channel->key));
2291 memcpy(channel->key, channel_key, key_len);
2292 memset(channel_key, 0, sizeof(channel_key));
2294 /* Encode channel key payload to be distributed on the channel */
2296 silc_channel_key_payload_encode(len, tmp,
2297 strlen(channel->channel_key->cipher->name),
2298 channel->channel_key->cipher->name,
2299 key_len, channel->key);
2301 /* If we are normal server then we will send it to our router. If we
2302 are router we will send it to all local servers that has clients on
2304 if (server->server_type == SILC_SERVER) {
2305 if (!server->standalone)
2306 silc_server_packet_send(server,
2307 cmd->server->id_entry->router->connection,
2308 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2314 /* Send to locally connected clients on the channel */
2315 silc_server_packet_send_local_channel(server, channel,
2316 SILC_PACKET_CHANNEL_KEY, 0,
2317 packet->data, packet->len, FALSE);
2319 silc_buffer_free(packet);
2323 silc_server_command_free(cmd);
2326 /* Server side of command NAMES. Resolves clients and their names currently
2327 joined on the requested channel. The name list is sent back to the
2330 SILC_SERVER_CMD_FUNC(names)
2332 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2333 SilcServer server = cmd->server;
2334 SilcChannelEntry channel;
2335 SilcChannelClientEntry chl;
2338 unsigned int i, len, len2, tmp_len, argc;
2340 char *name_list = NULL, *n;
2341 SilcBuffer client_id_list;
2342 SilcBuffer client_mode_list;
2344 SILC_LOG_DEBUG(("Start"));
2346 argc = silc_argument_get_arg_num(cmd->args);
2348 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2349 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2354 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2358 /* Get Channel ID */
2359 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2361 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2362 SILC_STATUS_ERR_NO_CHANNEL_ID);
2365 id = silc_id_payload_parse_id(tmp, tmp_len);
2367 /* Check whether the channel exists. If we are normal server and the
2368 channel does not exist we will send this same command to our router
2369 which will know if the channel exists. */
2370 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2372 if (server->server_type == SILC_SERVER && !server->standalone) {
2373 /* XXX Send names command */
2375 cmd->pending = TRUE;
2376 silc_server_command_pending(SILC_COMMAND_NAMES,
2377 silc_server_command_names, context);
2381 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2382 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2386 /* Assemble the name list now */
2389 silc_list_start(channel->user_list);
2391 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2392 n = chl->client->nickname;
2396 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2397 memcpy(name_list + (len - len2), n, len2);
2400 if (i == silc_list_count(channel->user_list) - 1)
2402 memcpy(name_list + len, ",", 1);
2410 /* Assemble the Client ID list now */
2411 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2412 silc_list_count(channel->user_list));
2413 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2414 silc_list_start(channel->user_list);
2415 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2418 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2419 silc_buffer_format(client_id_list,
2420 SILC_STR_UI_XNSTRING(idp->data, idp->len),
2422 silc_buffer_pull(client_id_list, idp->len);
2423 silc_buffer_free(idp);
2425 silc_buffer_push(client_id_list,
2426 client_id_list->data - client_id_list->head);
2428 /* Assemble mode list */
2429 client_mode_list = silc_buffer_alloc(4 *
2430 silc_list_count(channel->user_list));
2431 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2432 silc_list_start(channel->user_list);
2433 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2434 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2435 silc_buffer_pull(client_mode_list, 4);
2437 silc_buffer_push(client_mode_list,
2438 client_mode_list->data - client_mode_list->head);
2441 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2442 SILC_STATUS_OK, 0, 4,
2446 4, client_id_list->data,
2447 client_id_list->len,
2448 5, client_mode_list->data,
2449 client_mode_list->len);
2450 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2451 packet->data, packet->len, FALSE);
2453 silc_buffer_free(packet);
2454 silc_free(name_list);
2455 silc_buffer_free(client_id_list);
2456 silc_buffer_free(client_mode_list);
2460 silc_server_command_free(cmd);