5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
37 unsigned int arg_type,
39 unsigned int arg_len);
40 static void silc_server_command_free(SilcServerCommandContext cmd);
41 void silc_server_command_send_names(SilcServer server,
42 SilcSocketConnection sock,
43 SilcChannelEntry channel);
45 /* Server command list. */
46 SilcServerCommand silc_command_list[] =
48 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
49 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
54 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(connect, CONNECT,
59 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
60 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
62 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(restart, RESTART,
69 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
70 SILC_SERVER_CMD(close, CLOSE,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72 SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
73 SILC_SERVER_CMD(silcoper, SILCOPER,
74 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
75 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
76 SILC_SERVER_CMD(names, NAMES, SILC_CF_LAG | SILC_CF_REG),
81 /* 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 be executed when reply to a command has been
174 received. The `reply_cmd' is the command that will call the `callback'
175 with `context' when reply has been received. If `ident' is non-zero
176 the `callback' will be executed when received reply with command
177 identifier `ident'. */
179 void silc_server_command_pending(SilcServer server,
180 SilcCommand reply_cmd,
181 unsigned short ident,
182 SilcCommandCb callback,
185 SilcServerCommandPending *reply;
187 reply = silc_calloc(1, sizeof(*reply));
188 reply->reply_cmd = reply_cmd;
189 reply->ident = ident;
190 reply->context = context;
191 reply->callback = callback;
192 silc_dlist_add(server->pending_commands, reply);
195 /* Deletes pending command by reply command type. */
197 void silc_server_command_pending_del(SilcServer server,
198 SilcCommand reply_cmd,
199 unsigned short ident)
201 SilcServerCommandPending *r;
203 silc_dlist_start(server->pending_commands);
204 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
205 if (r->reply_cmd == reply_cmd && r->ident == ident) {
206 silc_dlist_del(server->pending_commands, r);
212 /* Checks for pending commands and marks callbacks to be called from
213 the command reply function. Returns TRUE if there were pending command. */
215 int silc_server_command_pending_check(SilcServer server,
216 SilcServerCommandReplyContext ctx,
218 unsigned short ident)
220 SilcServerCommandPending *r;
222 silc_dlist_start(server->pending_commands);
223 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
224 if (r->reply_cmd == command && r->ident == ident) {
225 ctx->context = r->context;
226 ctx->callback = r->callback;
235 /* Free's the command context allocated before executing the command */
237 static void silc_server_command_free(SilcServerCommandContext cmd)
240 silc_command_free_payload(cmd->payload);
245 /* Sends simple status message as command reply packet */
248 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
250 SilcCommandStatus status)
254 SILC_LOG_DEBUG(("Sending command status %d", status));
256 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
257 silc_server_packet_send(cmd->server, cmd->sock,
258 SILC_PACKET_COMMAND_REPLY, 0,
259 buffer->data, buffer->len, FALSE);
260 silc_buffer_free(buffer);
263 /* Sends command status reply with one extra argument. The argument
264 type must be sent as argument. */
267 silc_server_command_send_status_data(SilcServerCommandContext cmd,
269 SilcCommandStatus status,
270 unsigned int arg_type,
272 unsigned int arg_len)
276 SILC_LOG_DEBUG(("Sending command status %d", status));
278 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
279 arg_type, arg, arg_len);
280 silc_server_packet_send(cmd->server, cmd->sock,
281 SILC_PACKET_COMMAND_REPLY, 0,
282 buffer->data, buffer->len, FALSE);
283 silc_buffer_free(buffer);
286 /* Server side of command WHOIS. Processes user's query and sends found
287 results as command replies back to the client. */
289 SILC_SERVER_CMD_FUNC(whois)
291 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
292 SilcServer server = cmd->server;
293 char *tmp, *nick = NULL, *server_name = NULL;
294 unsigned int i, argc, count = 0, len, clients_count;
296 SilcClientID *client_id = NULL;
297 SilcBuffer packet, idp;
298 SilcClientEntry *clients = NULL, entry;
299 SilcCommandStatus status;
301 SILC_LOG_DEBUG(("Start"));
303 argc = silc_argument_get_arg_num(cmd->args);
305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
306 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
311 SILC_STATUS_ERR_TOO_MANY_PARAMS);
315 /* If client ID is in the command it must be used instead of nickname */
316 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
319 /* No ID, get the nickname@server string and parse it. */
320 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
322 if (strchr(tmp, '@')) {
323 len = strcspn(tmp, "@");
324 nick = silc_calloc(len + 1, sizeof(char));
325 memcpy(nick, tmp, len);
326 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
327 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
333 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
337 /* Command includes ID, use that */
338 client_id = silc_id_payload_parse_id(tmp, len);
342 /* Get the max count of reply messages allowed */
344 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
347 SILC_STATUS_ERR_TOO_MANY_PARAMS);
351 silc_free(server_name);
357 /* Protocol dictates that we must always send the received WHOIS request
358 to our router if we are normal server, so let's do it now unless we
359 are standalone. We will not send any replies to the client until we
360 have received reply from the router. */
361 if (!server->standalone) {
364 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
365 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
367 /* Send WHOIS command to our router */
368 silc_server_packet_send(server, (SilcSocketConnection)
369 server->id_entry->router->connection,
370 SILC_PACKET_COMMAND, cmd->packet->flags,
371 tmpbuf->data, tmpbuf->len, TRUE);
374 /* We are standalone, let's just do local search and send reply to
375 requesting client. */
377 /* Get all clients matching that nickname */
379 clients = silc_idlist_get_clients_by_nickname(server->local_list,
383 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
385 clients = silc_calloc(1, sizeof(*clients));
391 /* If we are router then we will check our global list as well. */
392 if (server->server_type == SILC_ROUTER) {
394 silc_idlist_find_client_by_nickname(server->global_list,
397 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
398 SILC_STATUS_ERR_NO_SUCH_NICK,
399 3, tmp, strlen(tmp));
406 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
407 SILC_STATUS_ERR_NO_SUCH_NICK,
408 3, tmp, strlen(tmp));
413 /* We are standalone and will send reply to client */
416 status = SILC_STATUS_OK;
417 if (clients_count > 1)
418 status = SILC_STATUS_LIST_START;
420 for (i = 0; i < clients_count; i++) {
423 if (count && i - 1 == count)
426 if (clients_count > 2)
427 status = SILC_STATUS_LIST_ITEM;
429 if (clients_count > 1 && i == clients_count - 1)
430 status = SILC_STATUS_LIST_END;
432 /* Send WHOIS reply */
433 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
434 tmp = silc_argument_get_first_arg(cmd->args, NULL);
437 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
438 char nh[256], uh[256];
439 unsigned char idle[4];
440 SilcSocketConnection hsock;
442 memset(uh, 0, sizeof(uh));
443 memset(nh, 0, sizeof(nh));
445 strncat(nh, entry->nickname, strlen(entry->nickname));
447 len = entry->router ? strlen(entry->router->server_name) :
448 strlen(server->server_name);
449 strncat(nh, entry->router ? entry->router->server_name :
450 server->server_name, len);
452 strncat(uh, entry->username, strlen(entry->username));
454 hsock = (SilcSocketConnection)entry->connection;
455 len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
456 strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
458 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
463 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
465 2, idp->data, idp->len,
469 strlen(entry->userinfo),
473 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
475 2, idp->data, idp->len,
483 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
485 2, idp->data, idp->len,
487 strlen(entry->nickname),
488 4, tmp, strlen(tmp)); /* XXX */
490 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
491 0, packet->data, packet->len, FALSE);
493 silc_buffer_free(packet);
494 silc_buffer_free(idp);
500 silc_free(client_id);
503 silc_server_command_free(cmd);
506 SILC_SERVER_CMD_FUNC(whowas)
510 SILC_SERVER_CMD_FUNC(identify)
512 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
513 SilcServer server = cmd->server;
514 char *tmp, *nick = NULL, *server_name = NULL;
515 unsigned int argc, count = 0, len;
517 SilcClientID *client_id = NULL;
518 SilcClientEntry entry;
519 SilcBuffer packet, idp;
521 SILC_LOG_DEBUG(("Start"));
523 argc = silc_argument_get_arg_num(cmd->args);
525 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
526 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
530 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
531 SILC_STATUS_ERR_TOO_MANY_PARAMS);
535 /* If client ID is in the command it must be used instead of nickname */
536 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
539 /* Get the nickname@server string and parse it. */
540 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
542 if (strchr(tmp, '@')) {
543 len = strcspn(tmp, "@");
544 nick = silc_calloc(len + 1, sizeof(char));
545 memcpy(nick, tmp, len);
546 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
547 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
552 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
553 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
557 /* Command includes ID, use that */
558 client_id = silc_id_payload_parse_id(tmp, len);
562 /* Get the max count of reply messages allowed */
564 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
567 SILC_STATUS_ERR_TOO_MANY_PARAMS);
575 entry = silc_idlist_find_client_by_nickname(server->local_list,
578 entry = silc_idlist_find_client_by_hash(server->global_list,
579 nick, server->md5hash);
581 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
584 /* If client was not found and if we are normal server and are connected
585 to a router we will make global query from the router. */
586 if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
588 SilcBuffer buffer = cmd->packet->buffer;
590 SILC_LOG_DEBUG(("Requesting identify from router"));
592 /* Send IDENTIFY command to our router */
593 silc_buffer_push(buffer, buffer->data - buffer->head);
594 silc_server_packet_forward(server, (SilcSocketConnection)
595 server->id_entry->router->connection,
596 buffer->data, buffer->len, TRUE);
600 /* If we are router we have checked our local list by nickname and our
601 global list by hash so far. It is possible that the client is still not
602 found and we'll check it from local list by hash. */
603 if (!entry && server->server_type == SILC_ROUTER)
604 entry = silc_idlist_find_client_by_hash(server->local_list,
605 nick, server->md5hash);
608 /* The client definitely does not exist */
609 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
610 SILC_STATUS_ERR_NO_SUCH_NICK,
611 3, tmp, strlen(tmp));
615 /* Send IDENTIFY reply */
616 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
617 tmp = silc_argument_get_first_arg(cmd->args, NULL);
618 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
619 SILC_STATUS_OK, 0, 2,
620 2, idp->data, idp->len,
621 3, nick, strlen(nick));
622 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
623 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
624 silc_server_packet_send_dest(server, cmd->sock,
625 SILC_PACKET_COMMAND_REPLY, 0,
626 id, cmd->packet->src_id_type,
627 packet->data, packet->len, FALSE);
630 silc_server_packet_send(server, cmd->sock,
631 SILC_PACKET_COMMAND_REPLY, 0,
632 packet->data, packet->len, FALSE);
635 silc_buffer_free(packet);
636 silc_buffer_free(idp);
638 silc_free(client_id);
644 silc_free(server_name);
645 silc_server_command_free(cmd);
648 /* Checks string for bad characters and returns TRUE if they are found. */
650 static int silc_server_command_bad_chars(char *nick)
652 if (strchr(nick, '\\')) return TRUE;
653 if (strchr(nick, '\"')) return TRUE;
654 if (strchr(nick, '´')) return TRUE;
655 if (strchr(nick, '`')) return TRUE;
656 if (strchr(nick, '\'')) return TRUE;
657 if (strchr(nick, '*')) return TRUE;
658 if (strchr(nick, '/')) return TRUE;
659 if (strchr(nick, '@')) return TRUE;
664 /* Server side of command NICK. Sets nickname for user. Setting
665 nickname causes generation of a new client ID for the client. The
666 new client ID is sent to the client after changing the nickname. */
668 SILC_SERVER_CMD_FUNC(nick)
670 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
671 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
672 SilcServer server = cmd->server;
673 SilcBuffer packet, nidp, oidp;
674 SilcClientID *new_id;
677 SILC_LOG_DEBUG(("Start"));
679 /* Check number of arguments */
680 if (silc_argument_get_arg_num(cmd->args) < 1) {
681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
682 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
687 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
688 if (silc_server_command_bad_chars(nick) == TRUE) {
689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
690 SILC_STATUS_ERR_BAD_NICKNAME);
694 /* Create new Client ID */
695 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
696 cmd->server->md5hash, nick,
699 /* Send notify about nickname change to our router. We send the new
700 ID and ask to replace it with the old one. */
701 if (cmd->server->server_type == SILC_SERVER && !cmd->server->standalone)
702 silc_server_send_replace_id(server, server->id_entry->router->connection,
704 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
705 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
707 /* If we are router we have to distribute the new Client ID to all
709 if (cmd->server->server_type == SILC_ROUTER && !cmd->server->standalone)
710 silc_server_send_replace_id(server, server->id_entry->router->connection,
712 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
713 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
715 /* Remove old cache entry */
716 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
719 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
723 memset(client->id, 0, SILC_ID_CLIENT_LEN);
724 silc_free(client->id);
727 /* Save the nickname as this client is our local client */
728 if (client->nickname)
729 silc_free(client->nickname);
731 client->nickname = strdup(nick);
734 /* Update client cache */
735 silc_idcache_add(server->local_list->clients, client->nickname,
736 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
738 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
740 /* Send NICK_CHANGE notify */
741 silc_server_send_notify_on_channels(server, client,
742 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
743 oidp->data, oidp->len,
744 nidp->data, nidp->len);
746 /* Send the new Client ID as reply command back to client */
747 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
748 SILC_STATUS_OK, 0, 1,
749 2, nidp->data, nidp->len);
750 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
751 0, packet->data, packet->len, FALSE);
753 silc_buffer_free(packet);
754 silc_buffer_free(nidp);
755 silc_buffer_free(oidp);
758 silc_server_command_free(cmd);
761 SILC_SERVER_CMD_FUNC(list)
765 /* Server side of TOPIC command. Sets topic for channel and/or returns
766 current topic to client. */
768 SILC_SERVER_CMD_FUNC(topic)
770 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
771 SilcServer server = cmd->server;
772 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
773 SilcChannelID *channel_id;
774 SilcChannelEntry channel;
775 SilcChannelClientEntry chl;
776 SilcBuffer packet, idp;
778 unsigned int argc, tmp_len;
780 /* Check number of arguments */
781 argc = silc_argument_get_arg_num(cmd->args);
783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
784 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
789 SILC_STATUS_ERR_TOO_MANY_PARAMS);
794 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
797 SILC_STATUS_ERR_NO_CHANNEL_ID);
800 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
802 /* Check whether the channel exists */
803 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
806 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
812 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
815 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
819 if (strlen(tmp) > 256) {
820 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
821 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
825 /* See whether has rights to change topic */
826 silc_list_start(channel->user_list);
827 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
828 if (chl->client == client) {
829 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
830 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
831 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
839 /* Set the topic for channel */
841 silc_free(channel->topic);
842 channel->topic = strdup(tmp);
844 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
846 /* Send notify about topic change to all clients on the channel */
847 silc_server_send_notify_to_channel(server, channel,
848 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
850 channel->topic, strlen(channel->topic));
851 silc_buffer_free(idp);
854 /* Send the topic to client as reply packet */
855 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
857 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
858 SILC_STATUS_OK, 0, 2,
859 2, idp->data, idp->len,
861 strlen(channel->topic));
863 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
864 SILC_STATUS_OK, 0, 1,
865 2, idp->data, idp->len);
866 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
867 0, packet->data, packet->len, FALSE);
869 silc_buffer_free(packet);
870 silc_buffer_free(idp);
871 silc_free(channel_id);
874 silc_server_command_free(cmd);
877 /* Server side of INVITE command. Invites some client to join some channel. */
879 SILC_SERVER_CMD_FUNC(invite)
881 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
882 SilcServer server = cmd->server;
883 SilcSocketConnection sock = cmd->sock, dest_sock;
884 SilcClientEntry sender, dest;
885 SilcClientID *dest_id;
886 SilcChannelEntry channel;
887 SilcChannelID *channel_id;
890 unsigned int argc, len;
892 /* Check number of arguments */
893 argc = silc_argument_get_arg_num(cmd->args);
895 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
896 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
900 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
901 SILC_STATUS_ERR_TOO_MANY_PARAMS);
905 /* Get destination ID */
906 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
908 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
909 SILC_STATUS_ERR_NO_CLIENT_ID);
912 dest_id = silc_id_payload_parse_id(tmp, len);
915 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
917 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
918 SILC_STATUS_ERR_NO_CHANNEL_ID);
921 channel_id = silc_id_payload_parse_id(tmp, len);
923 /* Check whether the channel exists */
924 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
927 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
931 /* Check whether the sender of this command is on the channel. */
932 sender = (SilcClientEntry)sock->user_data;
933 if (!silc_server_client_on_channel(sender, channel)) {
934 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
935 SILC_STATUS_ERR_NOT_ON_CHANNEL);
939 /* Check whether the channel is invite-only channel. If yes then the
940 sender of this command must be at least channel operator. */
941 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
942 SilcChannelClientEntry chl;
944 silc_list_start(channel->user_list);
945 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
946 if (chl->client == sender) {
947 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
949 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
956 /* Find the connection data for the destination. If it is local we will
957 send it directly otherwise we will send it to router for routing. */
958 dest = silc_idlist_find_client_by_id(server->local_list, dest_id);
960 dest_sock = (SilcSocketConnection)dest->connection;
962 dest_sock = silc_server_get_route(server, dest_id, SILC_ID_CLIENT);
964 /* Check whether the requested client is already on the channel. */
965 /* XXX if we are normal server we don't know about global clients on
966 the channel thus we must request it (NAMES command), check from
967 local cache as well. */
968 if (silc_server_client_on_channel(dest, channel)) {
969 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
970 SILC_STATUS_ERR_USER_ON_CHANNEL);
974 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
976 /* Send notify to the client that is invited to the channel */
977 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
978 SILC_NOTIFY_TYPE_INVITE, 2,
979 sidp->data, sidp->len, tmp, len);
981 /* Send command reply */
982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
985 silc_buffer_free(sidp);
988 silc_server_command_free(cmd);
991 /* Quits connection to client. This gets called if client won't
992 close the connection even when it has issued QUIT command. */
994 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
996 SilcServer server = (SilcServer)context;
997 SilcSocketConnection sock = server->sockets[fd];
999 /* Free all client specific data, such as client entry and entires
1000 on channels this client may be on. */
1001 silc_server_free_sock_user_data(server, sock);
1003 /* Close the connection on our side */
1004 silc_server_close_connection(server, sock);
1007 /* Quits SILC session. This is the normal way to disconnect client. */
1009 SILC_SERVER_CMD_FUNC(quit)
1011 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1012 SilcServer server = cmd->server;
1013 SilcSocketConnection sock = cmd->sock;
1015 SILC_LOG_DEBUG(("Start"));
1017 /* We quit the connection with little timeout */
1018 silc_task_register(server->timeout_queue, sock->sock,
1019 silc_server_command_quit_cb, server,
1020 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1022 silc_server_command_free(cmd);
1025 SILC_SERVER_CMD_FUNC(kill)
1029 /* Server side of command INFO. This sends information about us to
1030 the client. If client requested specific server we will send the
1031 command to that server. */
1033 SILC_SERVER_CMD_FUNC(info)
1035 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1036 SilcServer server = cmd->server;
1037 SilcBuffer packet, idp;
1039 char info_string[256], *dest_server;
1041 argc = silc_argument_get_arg_num(cmd->args);
1043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1044 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1048 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1049 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1053 /* Get server name */
1054 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1057 SILC_STATUS_ERR_NO_SUCH_SERVER);
1061 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1062 /* Send our reply */
1063 memset(info_string, 0, sizeof(info_string));
1064 snprintf(info_string, sizeof(info_string),
1065 "location: %s server: %s admin: %s <%s>",
1066 server->config->admin_info->location,
1067 server->config->admin_info->server_type,
1068 server->config->admin_info->admin_name,
1069 server->config->admin_info->admin_email);
1071 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1073 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1074 SILC_STATUS_OK, 0, 2,
1075 2, idp->data, idp->len,
1077 strlen(info_string));
1078 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1079 packet->data, packet->len, FALSE);
1081 silc_buffer_free(packet);
1082 silc_buffer_free(idp);
1084 /* Send this command to the requested server */
1086 if (server->server_type == SILC_SERVER && !server->standalone) {
1090 if (server->server_type == SILC_ROUTER) {
1096 silc_server_command_free(cmd);
1099 SILC_SERVER_CMD_FUNC(connect)
1103 /* Server side of command PING. This just replies to the ping. */
1105 SILC_SERVER_CMD_FUNC(ping)
1107 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1108 SilcServer server = cmd->server;
1110 unsigned int argc, len;
1113 argc = silc_argument_get_arg_num(cmd->args);
1115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1116 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1121 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1126 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1128 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1129 SILC_STATUS_ERR_NO_SERVER_ID);
1132 id = silc_id_payload_parse_id(tmp, len);
1134 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1135 /* Send our reply */
1136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1139 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1140 SILC_STATUS_ERR_NO_SUCH_SERVER);
1147 silc_server_command_free(cmd);
1150 SILC_SERVER_CMD_FUNC(oper)
1159 SilcChannelEntry channel;
1161 SilcClientEntry client;
1162 } JoinInternalContext;
1164 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1166 JoinInternalContext *ctx = (JoinInternalContext *)context;
1168 if (ctx->channel->key && ctx->channel->key_len) {
1171 clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1173 silc_server_send_notify_to_channel(ctx->server, ctx->channel,
1174 SILC_NOTIFY_TYPE_JOIN, 1,
1175 clidp->data, clidp->len);
1177 /* Send NAMES command reply to the joined channel so the user sees who
1178 is currently on the channel. */
1179 silc_server_command_send_names(ctx->server, ctx->client->connection,
1182 silc_buffer_free(clidp);
1185 silc_task_register(ctx->server->timeout_queue, fd,
1186 silc_server_command_join_notify, context,
1187 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1191 /* Assembles NAMES command and executes it. This is called when client
1192 joins to a channel and we wan't to send NAMES command reply to the
1195 void silc_server_command_send_names(SilcServer server,
1196 SilcSocketConnection sock,
1197 SilcChannelEntry channel)
1199 SilcServerCommandContext cmd;
1200 SilcBuffer buffer, idp;
1202 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1203 buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1204 1, idp->data, idp->len);
1206 cmd = silc_calloc(1, sizeof(*cmd));
1207 cmd->payload = silc_command_payload_parse(buffer);
1208 cmd->args = silc_command_get_args(cmd->payload);
1209 cmd->server = server;
1211 cmd->pending = FALSE;
1213 silc_server_command_names((void *)cmd);
1218 /* Internal routine to join channel. The channel sent to this function
1219 has been either created or resolved from ID lists. This joins the sent
1220 client to the channel. */
1223 silc_server_command_join_channel(SilcServer server,
1224 SilcServerCommandContext cmd,
1225 SilcChannelEntry channel,
1228 SilcSocketConnection sock = cmd->sock;
1230 unsigned int tmp_len;
1231 unsigned char *passphrase = NULL, mode[4];
1232 SilcClientEntry client;
1233 SilcChannelClientEntry chl;
1234 SilcBuffer packet, idp;
1239 /* Get passphrase */
1240 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1242 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1243 memcpy(passphrase, tmp, tmp_len);
1247 * Check channel modes
1250 /* Check invite list if channel is invite-only channel */
1251 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1252 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1253 /* Invite list is specified. Check whether client is invited in the
1254 list. If not, then check whether it has been invited otherwise. */
1257 /* XXX client must be invited to be able to join the channel */
1261 /* Check ban list if set */
1262 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1266 /* Check the channel passphrase if set. */
1267 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1268 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1269 strlen(channel->mode_data.passphrase))) {
1270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1271 SILC_STATUS_ERR_BAD_PASSWORD);
1276 /* Check user count limit if set. */
1277 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1278 if (silc_list_count(channel->user_list) + 1 >
1279 channel->mode_data.user_limit) {
1280 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1281 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1287 * Client is allowed to join to the channel. Make it happen.
1290 /* If the JOIN request was forwarded to us we will make a bit slower
1291 query to get the client pointer. Otherwise, we get the client pointer
1293 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1294 client = (SilcClientEntry)sock->user_data;
1296 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1297 client = silc_idlist_find_client_by_id(server->local_list, id);
1305 /* Check whether the client already is on the channel */
1306 if (silc_server_client_on_channel(client, channel)) {
1307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1308 SILC_STATUS_ERR_USER_ON_CHANNEL);
1312 /* Join the client to the channel by adding it to channel's user list.
1313 Add also the channel to client entry's channels list for fast cross-
1315 chl = silc_calloc(1, sizeof(*chl));
1317 chl->client = client;
1318 chl->channel = channel;
1319 silc_list_add(channel->user_list, chl);
1320 silc_list_add(client->channels, chl);
1322 /* Notify router about new user on channel. If we are normal server
1323 we send it to our router, if we are router we send it to our
1325 if (!server->standalone) {
1329 /* Send command reply to the client. Client receives the Channe ID,
1330 channel mode and possibly other information in this reply packet. */
1331 if (!cmd->pending) {
1332 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1333 SILC_PUT32_MSB(channel->mode, mode);
1335 if (!channel->topic)
1337 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1338 SILC_STATUS_OK, 0, 3,
1339 2, channel->channel_name,
1340 strlen(channel->channel_name),
1341 3, idp->data, idp->len,
1345 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1346 SILC_STATUS_OK, 0, 4,
1347 2, channel->channel_name,
1348 strlen(channel->channel_name),
1349 3, idp->data, idp->len,
1352 strlen(channel->topic));
1354 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1355 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1356 silc_server_packet_send_dest(cmd->server, cmd->sock,
1357 SILC_PACKET_COMMAND_REPLY, 0,
1358 id, cmd->packet->src_id_type,
1359 packet->data, packet->len, FALSE);
1362 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1363 packet->data, packet->len, FALSE);
1364 silc_buffer_free(packet);
1366 /* Send channel key to the client. Client cannot start transmitting
1367 to the channel until we have sent the key. */
1368 tmp_len = strlen(channel->channel_key->cipher->name);
1370 silc_channel_key_payload_encode(idp->len, idp->data,
1371 strlen(channel->channel_key->
1373 channel->channel_key->cipher->name,
1374 channel->key_len / 8, channel->key);
1376 silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
1377 packet->data, packet->len, FALSE);
1379 silc_buffer_free(packet);
1380 silc_buffer_free(idp);
1383 /* Finally, send notify message to all clients on the channel about
1384 new user on the channel. */
1385 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1386 if (!cmd->pending) {
1389 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1391 silc_server_send_notify_to_channel(server, channel,
1392 SILC_NOTIFY_TYPE_JOIN, 1,
1393 clidp->data, clidp->len);
1395 silc_buffer_free(clidp);
1397 /* This is pending command request. Send the notify after we have
1398 received the key for the channel from the router. */
1399 JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
1400 ctx->channel_name = channel->channel_name;
1401 ctx->nickname = client->nickname;
1402 ctx->username = client->username;
1403 ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
1404 ctx->channel = channel;
1405 ctx->server = server;
1406 ctx->client = client;
1407 silc_task_register(server->timeout_queue, sock->sock,
1408 silc_server_command_join_notify, ctx,
1409 0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1412 /* Send NAMES command reply to the joined channel so the user sees who
1413 is currently on the channel. */
1414 silc_server_command_send_names(server, sock, channel);
1419 silc_free(passphrase);
1422 /* Server side of command JOIN. Joins client into requested channel. If
1423 the channel does not exist it will be created. */
1425 SILC_SERVER_CMD_FUNC(join)
1427 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1428 SilcServer server = cmd->server;
1430 char *tmp, *channel_name = NULL, *cipher = NULL;
1431 SilcChannelEntry channel;
1432 unsigned int umode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
1434 SILC_LOG_DEBUG(("Start"));
1436 /* Check number of parameters */
1437 argc = silc_argument_get_arg_num(cmd->args);
1439 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1440 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1445 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1449 /* Get channel name */
1450 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1453 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1458 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1459 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1460 SILC_STATUS_ERR_BAD_CHANNEL);
1461 silc_free(channel_name);
1465 /* Get cipher name */
1466 cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1468 /* See if the channel exists */
1469 channel = silc_idlist_find_channel_by_name(server->local_list, channel_name);
1471 /* Channel not found */
1473 /* If we are standalone server we don't have a router, we just create
1474 the channel by ourselves. */
1475 if (server->standalone) {
1476 channel = silc_server_new_channel(server, server->id, cipher,
1480 /* The channel does not exist on our server. We send JOIN command to
1481 our router which will handle the joining procedure (either creates
1482 the channel if it doesn't exist or joins the client to it) - if we
1483 are normal server. */
1484 if (server->server_type == SILC_SERVER) {
1485 SilcBuffer buffer = cmd->packet->buffer;
1487 /* Forward the original JOIN command to the router */
1488 silc_buffer_push(buffer, buffer->data - buffer->head);
1489 silc_server_packet_forward(server, (SilcSocketConnection)
1490 server->id_entry->router->connection,
1491 buffer->data, buffer->len, TRUE);
1493 /* Add the command to be pending. It will be re-executed after
1494 router has replied back to us. */
1495 cmd->pending = TRUE;
1496 silc_server_command_pending(server, SILC_COMMAND_JOIN, 0,
1497 silc_server_command_join, context);
1501 /* We are router and the channel does not seem exist so we will check
1502 our global list as well for the channel. */
1503 channel = silc_idlist_find_channel_by_name(server->global_list,
1506 /* Channel really does not exist, create it */
1507 channel = silc_server_new_channel(server, server->id, cipher,
1509 umode |= SILC_CHANNEL_UMODE_CHANOP;
1510 umode |= SILC_CHANNEL_UMODE_CHANFO;
1515 /* Join to the channel */
1516 silc_server_command_join_channel(server, cmd, channel, umode);
1519 silc_server_command_free(cmd);
1522 /* Server side of command MOTD. Sends server's current "message of the
1523 day" to the client. */
1525 SILC_SERVER_CMD_FUNC(motd)
1527 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1528 SilcServer server = cmd->server;
1533 SILC_LOG_DEBUG(("Start"));
1535 argc = silc_argument_get_arg_num(cmd->args);
1537 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1538 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1543 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1547 /* XXX show currently only our motd */
1549 if (server->config && server->config->motd &&
1550 server->config->motd->motd_file) {
1553 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
1558 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
1564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
1569 silc_server_command_free(cmd);
1572 SILC_SERVER_CMD_FUNC(umode)
1576 /* Checks that client has rights to add or remove channel modes. If any
1577 of the checks fails FALSE is returned. */
1579 int silc_server_check_cmode_rights(SilcChannelEntry channel,
1580 SilcChannelClientEntry client,
1583 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1584 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1586 /* Check whether has rights to change anything */
1587 if (!is_op && !is_fo)
1590 /* Check whether has rights to change everything */
1594 /* We know that client is channel operator, check that they are not
1595 changing anything that requires channel founder rights. Rest of the
1596 modes are available automatically for channel operator. */
1598 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1599 if (is_op && !is_fo)
1602 if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
1603 if (is_op && !is_fo)
1608 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1609 if (is_op && !is_fo)
1612 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1613 if (is_op && !is_fo)
1618 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1619 if (is_op && !is_fo)
1622 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1623 if (is_op && !is_fo)
1631 /* Server side command of CMODE. Changes channel mode */
1633 SILC_SERVER_CMD_FUNC(cmode)
1635 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1636 SilcServer server = cmd->server;
1637 SilcSocketConnection sock = cmd->sock;
1638 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1639 SilcChannelID *channel_id;
1640 SilcClientID *client_id;
1641 SilcChannelEntry channel;
1642 SilcChannelClientEntry chl;
1643 SilcBuffer packet, cidp;
1644 unsigned char *tmp, *tmp_id, *tmp_mask;
1645 unsigned int argc, mode_mask, tmp_len, tmp_len2;
1648 SILC_LOG_DEBUG(("Start"));
1650 argc = silc_argument_get_arg_num(cmd->args);
1652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1653 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1657 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1658 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1662 /* Get Channel ID */
1663 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
1665 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1666 SILC_STATUS_ERR_NO_CHANNEL_ID);
1669 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
1671 /* Get the channel mode mask */
1672 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1675 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1678 SILC_GET32_MSB(mode_mask, tmp_mask);
1680 /* Get channel entry */
1681 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1683 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1684 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1688 /* Check whether this client is on the channel */
1689 if (!silc_server_client_on_channel(client, channel)) {
1690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1691 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1695 /* Get entry to the channel user list */
1696 silc_list_start(channel->user_list);
1697 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1698 if (chl->client == client)
1701 /* Check that client has rights to change any requested channel modes */
1702 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
1703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1704 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1709 * Check the modes. Modes that requires nothing special operation are
1713 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
1714 /* Channel uses private keys to protect traffic. Client(s) has set the
1715 key locally they want to use, server does not know that key. */
1716 /* Nothing interesting to do here now */
1718 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1719 /* The mode is removed and we need to generate and distribute
1720 new channel key. Clients are not using private channel keys
1721 anymore after this. */
1722 unsigned int key_len;
1723 unsigned char channel_key[32];
1725 /* XXX Duplicated code, make own function for this!! LEAVE uses this
1728 /* Re-generate channel key */
1729 key_len = channel->key_len / 8;
1730 for (i = 0; i < key_len; i++)
1731 channel_key[i] = silc_rng_get_byte(server->rng);
1732 channel->channel_key->cipher->set_key(channel->channel_key->context,
1733 channel_key, key_len);
1734 memset(channel->key, 0, key_len);
1735 silc_free(channel->key);
1736 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1737 memcpy(channel->key, channel_key, key_len);
1738 memset(channel_key, 0, sizeof(channel_key));
1740 /* Encode channel key payload to be distributed on the channel */
1742 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1743 strlen(channel->channel_key->
1745 channel->channel_key->cipher->name,
1746 key_len, channel->key);
1748 /* If we are normal server then we will send it to our router. If we
1749 are router we will send it to all local servers that has clients on
1751 if (server->server_type == SILC_SERVER) {
1752 if (!server->standalone)
1753 silc_server_packet_send(server,
1754 cmd->server->id_entry->router->connection,
1755 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1761 /* Send to locally connected clients on the channel */
1762 silc_server_packet_send_local_channel(server, channel,
1763 SILC_PACKET_CHANNEL_KEY, 0,
1764 packet->data, packet->len, FALSE);
1765 silc_buffer_free(packet);
1769 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
1770 /* User limit is set on channel */
1771 unsigned int user_limit;
1773 /* Get user limit */
1774 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1776 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
1777 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1778 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1782 SILC_GET32_MSB(user_limit, tmp);
1783 channel->mode_data.user_limit = user_limit;
1786 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
1787 /* User limit mode is unset. Remove user limit */
1788 channel->mode_data.user_limit = 0;
1791 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
1792 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1793 /* Passphrase has been set to channel */
1795 /* Get the passphrase */
1796 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1798 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1799 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1803 /* Save the passphrase */
1804 channel->mode_data.passphrase = strdup(tmp);
1807 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1808 /* Passphrase mode is unset. remove the passphrase */
1809 if (channel->mode_data.passphrase) {
1810 silc_free(channel->mode_data.passphrase);
1811 channel->mode_data.passphrase = NULL;
1816 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
1817 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
1818 /* Ban list is specified for channel */
1821 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1824 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1828 /* XXX check that channel founder is not banned */
1830 /* Save the ban list */
1831 channel->mode_data.ban_list = strdup(tmp);
1834 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1835 /* Ban mode is unset. Remove the entire ban list */
1836 if (channel->mode_data.ban_list) {
1837 silc_free(channel->mode_data.ban_list);
1838 channel->mode_data.ban_list = NULL;
1843 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
1844 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
1845 /* Invite list is specified for channel */
1847 /* Get invite list */
1848 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1850 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1851 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1855 /* Save the invite linst */
1856 channel->mode_data.invite_list = strdup(tmp);
1859 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1860 /* Invite list mode is unset. Remove the entire invite list */
1861 if (channel->mode_data.invite_list) {
1862 silc_free(channel->mode_data.invite_list);
1863 channel->mode_data.invite_list = NULL;
1868 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
1869 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1870 /* Cipher to use protect the traffic */
1871 unsigned int key_len = 128;
1872 unsigned char channel_key[32];
1876 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
1878 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1879 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1883 cp = strchr(tmp, ':');
1889 /* XXX Duplicated code, make own function for this!! */
1891 /* Delete old cipher and allocate the new one */
1892 silc_cipher_free(channel->channel_key);
1893 silc_cipher_alloc(tmp, &channel->channel_key);
1895 /* Re-generate channel key */
1897 if (key_len > sizeof(channel_key))
1898 key_len = sizeof(channel_key);
1900 for (i = 0; i < key_len; i++)
1901 channel_key[i] = silc_rng_get_byte(server->rng);
1902 channel->channel_key->cipher->set_key(channel->channel_key->context,
1903 channel_key, key_len);
1904 memset(channel->key, 0, key_len);
1905 silc_free(channel->key);
1906 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1907 memcpy(channel->key, channel_key, key_len);
1908 memset(channel_key, 0, sizeof(channel_key));
1910 /* Encode channel key payload to be distributed on the channel */
1912 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1913 strlen(channel->channel_key->
1915 channel->channel_key->cipher->name,
1916 key_len, channel->key);
1918 /* If we are normal server then we will send it to our router. If we
1919 are router we will send it to all local servers that has clients on
1921 if (server->server_type == SILC_SERVER) {
1922 if (!server->standalone)
1923 silc_server_packet_send(server,
1924 cmd->server->id_entry->router->connection,
1925 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1931 /* Send to locally connected clients on the channel */
1932 silc_server_packet_send_local_channel(server, channel,
1933 SILC_PACKET_CHANNEL_KEY, 0,
1934 packet->data, packet->len, FALSE);
1935 silc_buffer_free(packet);
1938 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1939 /* Cipher mode is unset. Remove the cipher and revert back to
1941 unsigned int key_len;
1942 unsigned char channel_key[32];
1944 if (channel->mode_data.cipher) {
1945 silc_free(channel->mode_data.cipher);
1946 channel->mode_data.cipher = NULL;
1947 channel->mode_data.key_len = 0;
1950 /* Generate new cipher and key for the channel */
1952 /* XXX Duplicated code, make own function for this!! */
1954 /* Delete old cipher and allocate default one */
1955 silc_cipher_free(channel->channel_key);
1956 if (!channel->cipher)
1957 silc_cipher_alloc("twofish", &channel->channel_key);
1959 silc_cipher_alloc(channel->cipher, &channel->channel_key);
1961 /* Re-generate channel key */
1962 key_len = channel->key_len / 8;
1963 for (i = 0; i < key_len; i++)
1964 channel_key[i] = silc_rng_get_byte(server->rng);
1965 channel->channel_key->cipher->set_key(channel->channel_key->context,
1966 channel_key, key_len);
1967 memset(channel->key, 0, key_len);
1968 silc_free(channel->key);
1969 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1970 memcpy(channel->key, channel_key, key_len);
1971 memset(channel_key, 0, sizeof(channel_key));
1973 /* Encode channel key payload to be distributed on the channel */
1975 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1976 strlen(channel->channel_key->
1978 channel->channel_key->cipher->name,
1979 key_len, channel->key);
1981 /* If we are normal server then we will send it to our router. If we
1982 are router we will send it to all local servers that has clients on
1984 if (server->server_type == SILC_SERVER) {
1985 if (!server->standalone)
1986 silc_server_packet_send(server,
1987 cmd->server->id_entry->router->connection,
1988 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1994 /* Send to locally connected clients on the channel */
1995 silc_server_packet_send_local_channel(server, channel,
1996 SILC_PACKET_CHANNEL_KEY, 0,
1997 packet->data, packet->len, FALSE);
1998 silc_buffer_free(packet);
2002 /* Finally, set the mode */
2003 channel->mode = mode_mask;
2005 /* Send CMODE_CHANGE notify */
2006 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2007 silc_server_send_notify_to_channel(server, channel,
2008 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2009 cidp->data, cidp->len,
2013 /* Send command reply to sender */
2014 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2015 SILC_STATUS_OK, 0, 1,
2017 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2018 packet->data, packet->len, FALSE);
2020 silc_buffer_free(packet);
2021 silc_free(channel_id);
2024 silc_server_command_free(cmd);
2027 /* Server side of CUMODE command. Changes client's mode on a channel. */
2029 SILC_SERVER_CMD_FUNC(cumode)
2031 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2032 SilcServer server = cmd->server;
2033 SilcSocketConnection sock = cmd->sock;
2034 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2035 SilcChannelID *channel_id;
2036 SilcClientID *client_id;
2037 SilcChannelEntry channel;
2038 SilcClientEntry target_client;
2039 SilcChannelClientEntry chl;
2040 SilcBuffer packet, idp;
2041 unsigned char *tmp, *tmp_id, *tmp_mask;
2042 unsigned int argc, target_mask, sender_mask, tmp_len;
2043 int i, notify = FALSE;
2045 SILC_LOG_DEBUG(("Start"));
2047 argc = silc_argument_get_arg_num(cmd->args);
2049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2050 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2054 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2055 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2059 /* Get Channel ID */
2060 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2063 SILC_STATUS_ERR_NO_CHANNEL_ID);
2066 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2068 /* Get channel entry */
2069 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
2071 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2072 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2076 /* Check whether sender is on the channel */
2077 if (!silc_server_client_on_channel(client, channel)) {
2078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2079 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2083 /* Check that client has rights to change other's rights */
2084 silc_list_start(channel->user_list);
2085 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2086 if (chl->client == client) {
2087 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2088 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2089 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2090 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2094 sender_mask = chl->mode;
2099 /* Get the target client's channel mode mask */
2100 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2102 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2103 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2106 SILC_GET32_MSB(target_mask, tmp_mask);
2108 /* Get target Client ID */
2109 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2111 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2112 SILC_STATUS_ERR_NO_CHANNEL_ID);
2115 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2117 /* Get target client's entry */
2118 target_client = silc_idlist_find_client_by_id(server->local_list, client_id);
2120 /* XXX If target client is not one of mine send to primary route */
2123 /* Check whether target client is on the channel */
2124 if (!silc_server_client_on_channel(target_client, channel)) {
2125 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2126 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2130 /* Get entry to the channel user list */
2131 silc_list_start(channel->user_list);
2132 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2133 if (chl->client == target_client)
2140 /* If the target client is founder, no one else can change their mode
2142 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2143 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2144 SILC_STATUS_ERR_NOT_YOU);
2148 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2149 /* Cannot promote anyone to channel founder */
2150 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2151 SILC_STATUS_ERR_NOT_YOU);
2154 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2155 if (target_client == client) {
2156 /* Remove channel founder rights from itself */
2157 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2160 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2161 SILC_STATUS_ERR_NOT_YOU);
2167 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2168 /* Promote to operator */
2169 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2170 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2174 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2175 /* Demote to normal user */
2176 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2181 /* Send notify to channel, notify only if mode was actually changed. */
2183 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2184 silc_server_send_notify_to_channel(server, channel,
2185 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2186 idp->data, idp->len,
2187 tmp_mask, 4, tmp_id, tmp_len);
2188 silc_buffer_free(idp);
2191 /* Send command reply to sender */
2192 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2193 SILC_STATUS_OK, 0, 2,
2195 3, tmp_id, tmp_len);
2196 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2197 packet->data, packet->len, FALSE);
2199 silc_buffer_free(packet);
2200 silc_free(channel_id);
2201 silc_free(client_id);
2204 silc_server_command_free(cmd);
2207 /* Server side of KICK command. Kicks client out of channel. */
2209 SILC_SERVER_CMD_FUNC(kick)
2211 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2212 SilcServer server = cmd->server;
2213 SilcSocketConnection sock = cmd->sock;
2214 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2218 SILC_SERVER_CMD_FUNC(restart)
2222 SILC_SERVER_CMD_FUNC(close)
2226 SILC_SERVER_CMD_FUNC(die)
2230 SILC_SERVER_CMD_FUNC(silcoper)
2234 /* Server side command of LEAVE. Removes client from a channel. */
2236 SILC_SERVER_CMD_FUNC(leave)
2238 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2239 SilcServer server = cmd->server;
2240 SilcSocketConnection sock = cmd->sock;
2241 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2243 SilcChannelEntry channel;
2245 unsigned int i, argc, key_len, len;
2246 unsigned char *tmp, channel_key[32];
2248 SILC_LOG_DEBUG(("Start"));
2250 argc = silc_argument_get_arg_num(cmd->args);
2252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2253 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2257 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2258 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2262 /* Get Channel ID */
2263 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2266 SILC_STATUS_ERR_NO_CHANNEL_ID);
2269 id = silc_id_payload_parse_id(tmp, len);
2271 /* Get channel entry */
2272 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2274 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2275 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2279 /* Check whether this client is on the channel */
2280 if (!silc_server_client_on_channel(id_entry, channel)) {
2281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2282 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2286 /* Notify routers that they should remove this client from their list
2287 of clients on the channel. */
2288 if (!server->standalone)
2289 silc_server_send_remove_channel_user(server,
2290 server->id_entry->router->connection,
2291 server->server_type == SILC_ROUTER ?
2292 TRUE : FALSE, id_entry->id, id);
2294 /* Remove client from channel */
2295 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2300 /* If the channel does not exist anymore we won't send anything */
2304 /* Re-generate channel key */
2305 key_len = channel->key_len / 8;
2306 for (i = 0; i < key_len; i++)
2307 channel_key[i] = silc_rng_get_byte(server->rng);
2308 channel->channel_key->cipher->set_key(channel->channel_key->context,
2309 channel_key, key_len);
2310 memset(channel->key, 0, key_len);
2311 silc_free(channel->key);
2312 channel->key = silc_calloc(key_len, sizeof(*channel->key));
2313 memcpy(channel->key, channel_key, key_len);
2314 memset(channel_key, 0, sizeof(channel_key));
2316 /* Encode channel key payload to be distributed on the channel */
2318 silc_channel_key_payload_encode(len, tmp,
2319 strlen(channel->channel_key->cipher->name),
2320 channel->channel_key->cipher->name,
2321 key_len, channel->key);
2323 /* If we are normal server then we will send it to our router. If we
2324 are router we will send it to all local servers that has clients on
2326 if (server->server_type == SILC_SERVER) {
2327 if (!server->standalone)
2328 silc_server_packet_send(server,
2329 cmd->server->id_entry->router->connection,
2330 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2336 /* Send to locally connected clients on the channel */
2337 silc_server_packet_send_local_channel(server, channel,
2338 SILC_PACKET_CHANNEL_KEY, 0,
2339 packet->data, packet->len, FALSE);
2341 silc_buffer_free(packet);
2345 silc_server_command_free(cmd);
2348 /* Server side of command NAMES. Resolves clients and their names currently
2349 joined on the requested channel. The name list is sent back to the
2352 SILC_SERVER_CMD_FUNC(names)
2354 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2355 SilcServer server = cmd->server;
2356 SilcChannelEntry channel;
2357 SilcChannelClientEntry chl;
2360 unsigned int i, len, len2, tmp_len, argc;
2362 char *name_list = NULL, *n;
2363 SilcBuffer client_id_list;
2364 SilcBuffer client_mode_list;
2366 SILC_LOG_DEBUG(("Start"));
2368 argc = silc_argument_get_arg_num(cmd->args);
2370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2371 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2375 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2376 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2380 /* Get Channel ID */
2381 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2384 SILC_STATUS_ERR_NO_CHANNEL_ID);
2387 id = silc_id_payload_parse_id(tmp, tmp_len);
2389 /* Check whether the channel exists. If we are normal server and the
2390 channel does not exist we will send this same command to our router
2391 which will know if the channel exists. */
2392 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2394 if (server->server_type == SILC_SERVER && !server->standalone) {
2395 /* XXX Send names command */
2397 cmd->pending = TRUE;
2398 silc_server_command_pending(server, SILC_COMMAND_NAMES, 0,
2399 silc_server_command_names, context);
2403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2404 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2408 /* Assemble the name list now */
2411 silc_list_start(channel->user_list);
2413 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2414 n = chl->client->nickname;
2418 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2419 memcpy(name_list + (len - len2), n, len2);
2422 if (i == silc_list_count(channel->user_list) - 1)
2424 memcpy(name_list + len, ",", 1);
2432 /* Assemble the Client ID list now */
2433 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2434 silc_list_count(channel->user_list));
2435 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2436 silc_list_start(channel->user_list);
2437 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2440 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2441 silc_buffer_format(client_id_list,
2442 SILC_STR_UI_XNSTRING(idp->data, idp->len),
2444 silc_buffer_pull(client_id_list, idp->len);
2445 silc_buffer_free(idp);
2447 silc_buffer_push(client_id_list,
2448 client_id_list->data - client_id_list->head);
2450 /* Assemble mode list */
2451 client_mode_list = silc_buffer_alloc(4 *
2452 silc_list_count(channel->user_list));
2453 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2454 silc_list_start(channel->user_list);
2455 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2456 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2457 silc_buffer_pull(client_mode_list, 4);
2459 silc_buffer_push(client_mode_list,
2460 client_mode_list->data - client_mode_list->head);
2463 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2464 SILC_STATUS_OK, 0, 4,
2468 4, client_id_list->data,
2469 client_id_list->len,
2470 5, client_mode_list->data,
2471 client_mode_list->len);
2472 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2473 packet->data, packet->len, FALSE);
2475 silc_buffer_free(packet);
2476 silc_free(name_list);
2477 silc_buffer_free(client_id_list);
2478 silc_buffer_free(client_mode_list);
2482 silc_server_command_free(cmd);