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 SilcDList silc_command_pending;
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(SilcCommand reply_cmd,
180 unsigned short ident,
181 SilcCommandCb callback,
184 SilcServerCommandPending *reply;
186 reply = silc_calloc(1, sizeof(*reply));
187 reply->reply_cmd = reply_cmd;
188 reply->ident = ident;
189 reply->context = context;
190 reply->callback = callback;
191 silc_dlist_add(silc_command_pending, reply);
194 /* Deletes pending command by reply command type. */
196 void silc_server_command_pending_del(SilcCommand reply_cmd,
197 unsigned short ident)
199 SilcServerCommandPending *r;
201 while ((r = silc_dlist_get(silc_command_pending)) != SILC_LIST_END) {
202 if (r->reply_cmd == reply_cmd && r->ident == ident) {
203 silc_dlist_del(silc_command_pending, r);
209 /* Checks for pending commands and marks callbacks to be called from
210 the command reply function. Returns TRUE if there were pending command. */
212 int silc_server_command_pending_check(SilcServerCommandReplyContext ctx,
214 unsigned short ident)
216 SilcServerCommandPending *r;
218 while ((r = silc_dlist_get(silc_command_pending)) != SILC_LIST_END) {
219 if (r->reply_cmd == command && r->ident == ident) {
220 ctx->context = r->context;
221 ctx->callback = r->callback;
230 /* Free's the command context allocated before executing the command */
232 static void silc_server_command_free(SilcServerCommandContext cmd)
235 silc_command_free_payload(cmd->payload);
240 /* Sends simple status message as command reply packet */
243 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
245 SilcCommandStatus status)
249 SILC_LOG_DEBUG(("Sending command status %d", status));
251 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
252 silc_server_packet_send(cmd->server, cmd->sock,
253 SILC_PACKET_COMMAND_REPLY, 0,
254 buffer->data, buffer->len, FALSE);
255 silc_buffer_free(buffer);
258 /* Sends command status reply with one extra argument. The argument
259 type must be sent as argument. */
262 silc_server_command_send_status_data(SilcServerCommandContext cmd,
264 SilcCommandStatus status,
265 unsigned int arg_type,
267 unsigned int arg_len)
271 SILC_LOG_DEBUG(("Sending command status %d", status));
273 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
274 arg_type, arg, arg_len);
275 silc_server_packet_send(cmd->server, cmd->sock,
276 SILC_PACKET_COMMAND_REPLY, 0,
277 buffer->data, buffer->len, FALSE);
278 silc_buffer_free(buffer);
281 /* Server side of command WHOIS. Processes user's query and sends found
282 results as command replies back to the client. */
284 SILC_SERVER_CMD_FUNC(whois)
286 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
287 SilcServer server = cmd->server;
288 char *tmp, *nick = NULL, *server_name = NULL;
289 unsigned int i, argc, count = 0, len, clients_count;
291 SilcClientID *client_id = NULL;
292 SilcBuffer packet, idp;
293 SilcClientEntry *clients = NULL, entry;
294 SilcCommandStatus status;
296 SILC_LOG_DEBUG(("Start"));
298 argc = silc_argument_get_arg_num(cmd->args);
300 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
301 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
306 SILC_STATUS_ERR_TOO_MANY_PARAMS);
310 /* If client ID is in the command it must be used instead of nickname */
311 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
314 /* No ID, get the nickname@server string and parse it. */
315 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
317 if (strchr(tmp, '@')) {
318 len = strcspn(tmp, "@");
319 nick = silc_calloc(len + 1, sizeof(char));
320 memcpy(nick, tmp, len);
321 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
322 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
328 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
332 /* Command includes ID, use that */
333 client_id = silc_id_payload_parse_id(tmp, len);
337 /* Get the max count of reply messages allowed */
339 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
342 SILC_STATUS_ERR_TOO_MANY_PARAMS);
346 silc_free(server_name);
352 /* Protocol dictates that we must always send the received WHOIS request
353 to our router if we are normal server, so let's do it now unless we
354 are standalone. We will not send any replies to the client until we
355 have received reply from the router. */
356 if (!server->standalone) {
359 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
360 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
362 /* Send WHOIS command to our router */
363 silc_server_packet_send(server, (SilcSocketConnection)
364 server->id_entry->router->connection,
365 SILC_PACKET_COMMAND, cmd->packet->flags,
366 tmpbuf->data, tmpbuf->len, TRUE);
369 /* We are standalone, let's just do local search and send reply to
370 requesting client. */
372 /* Get all clients matching that nickname */
374 clients = silc_idlist_get_clients_by_nickname(server->local_list,
378 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
380 clients = silc_calloc(1, sizeof(*clients));
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));
401 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
402 SILC_STATUS_ERR_NO_SUCH_NICK,
403 3, tmp, strlen(tmp));
408 /* We are standalone and will send reply to client */
411 status = SILC_STATUS_OK;
412 if (clients_count > 1)
413 status = SILC_STATUS_LIST_START;
415 for (i = 0; i < clients_count; i++) {
418 if (count && i - 1 == count)
421 if (clients_count > 2)
422 status = SILC_STATUS_LIST_ITEM;
424 if (clients_count > 1 && i == clients_count - 1)
425 status = SILC_STATUS_LIST_END;
427 /* Send WHOIS reply */
428 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
429 tmp = silc_argument_get_first_arg(cmd->args, NULL);
432 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
433 char nh[256], uh[256];
434 unsigned char idle[4];
435 SilcSocketConnection hsock;
437 memset(uh, 0, sizeof(uh));
438 memset(nh, 0, sizeof(nh));
440 strncat(nh, entry->nickname, strlen(entry->nickname));
442 len = entry->router ? strlen(entry->router->server_name) :
443 strlen(server->server_name);
444 strncat(nh, entry->router ? entry->router->server_name :
445 server->server_name, len);
447 strncat(uh, entry->username, strlen(entry->username));
449 hsock = (SilcSocketConnection)entry->connection;
450 len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
451 strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
453 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
458 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
460 2, idp->data, idp->len,
464 strlen(entry->userinfo),
468 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
470 2, idp->data, idp->len,
478 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
480 2, idp->data, idp->len,
482 strlen(entry->nickname),
483 4, tmp, strlen(tmp)); /* XXX */
485 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
486 0, packet->data, packet->len, FALSE);
488 silc_buffer_free(packet);
489 silc_buffer_free(idp);
495 silc_free(client_id);
498 silc_server_command_free(cmd);
501 SILC_SERVER_CMD_FUNC(whowas)
505 SILC_SERVER_CMD_FUNC(identify)
507 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
508 SilcServer server = cmd->server;
509 char *tmp, *nick = NULL, *server_name = NULL;
510 unsigned int argc, count = 0, len;
512 SilcClientID *client_id = NULL;
513 SilcClientEntry entry;
514 SilcBuffer packet, idp;
516 SILC_LOG_DEBUG(("Start"));
518 argc = silc_argument_get_arg_num(cmd->args);
520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
521 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
525 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
526 SILC_STATUS_ERR_TOO_MANY_PARAMS);
530 /* If client ID is in the command it must be used instead of nickname */
531 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
534 /* Get the nickname@server string and parse it. */
535 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
537 if (strchr(tmp, '@')) {
538 len = strcspn(tmp, "@");
539 nick = silc_calloc(len + 1, sizeof(char));
540 memcpy(nick, tmp, len);
541 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
542 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
547 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
548 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
552 /* Command includes ID, use that */
553 client_id = silc_id_payload_parse_id(tmp, len);
557 /* Get the max count of reply messages allowed */
559 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
561 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
562 SILC_STATUS_ERR_TOO_MANY_PARAMS);
570 entry = silc_idlist_find_client_by_nickname(server->local_list,
573 entry = silc_idlist_find_client_by_hash(server->global_list,
574 nick, server->md5hash);
576 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
579 /* If client was not found and if we are normal server and are connected
580 to a router we will make global query from the router. */
581 if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
583 SilcBuffer buffer = cmd->packet->buffer;
585 SILC_LOG_DEBUG(("Requesting identify from router"));
587 /* Send IDENTIFY command to our router */
588 silc_buffer_push(buffer, buffer->data - buffer->head);
589 silc_server_packet_forward(server, (SilcSocketConnection)
590 server->id_entry->router->connection,
591 buffer->data, buffer->len, TRUE);
595 /* If we are router we have checked our local list by nickname and our
596 global list by hash so far. It is possible that the client is still not
597 found and we'll check it from local list by hash. */
598 if (!entry && server->server_type == SILC_ROUTER)
599 entry = silc_idlist_find_client_by_hash(server->local_list,
600 nick, server->md5hash);
603 /* The client definitely does not exist */
604 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
605 SILC_STATUS_ERR_NO_SUCH_NICK,
606 3, tmp, strlen(tmp));
610 /* Send IDENTIFY reply */
611 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
612 tmp = silc_argument_get_first_arg(cmd->args, NULL);
613 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
614 SILC_STATUS_OK, 0, 2,
615 2, idp->data, idp->len,
616 3, nick, strlen(nick));
617 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
618 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
619 silc_server_packet_send_dest(server, cmd->sock,
620 SILC_PACKET_COMMAND_REPLY, 0,
621 id, cmd->packet->src_id_type,
622 packet->data, packet->len, FALSE);
625 silc_server_packet_send(server, cmd->sock,
626 SILC_PACKET_COMMAND_REPLY, 0,
627 packet->data, packet->len, FALSE);
630 silc_buffer_free(packet);
631 silc_buffer_free(idp);
633 silc_free(client_id);
639 silc_free(server_name);
640 silc_server_command_free(cmd);
643 /* Checks string for bad characters and returns TRUE if they are found. */
645 static int silc_server_command_bad_chars(char *nick)
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;
654 if (strchr(nick, '@')) return TRUE;
659 /* Server side of command NICK. Sets nickname for user. Setting
660 nickname causes generation of a new client ID for the client. The
661 new client ID is sent to the client after changing the nickname. */
663 SILC_SERVER_CMD_FUNC(nick)
665 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
666 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
667 SilcServer server = cmd->server;
668 SilcBuffer packet, nidp, oidp;
669 SilcClientID *new_id;
672 SILC_LOG_DEBUG(("Start"));
674 /* Check number of arguments */
675 if (silc_argument_get_arg_num(cmd->args) < 1) {
676 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
677 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
682 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
683 if (silc_server_command_bad_chars(nick) == TRUE) {
684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
685 SILC_STATUS_ERR_BAD_NICKNAME);
689 /* Create new Client ID */
690 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
691 cmd->server->md5hash, nick,
694 /* Send notify about nickname change to our router. We send the new
695 ID and ask to replace it with the old one. */
696 if (cmd->server->server_type == SILC_SERVER && !cmd->server->standalone)
697 silc_server_send_replace_id(server, server->id_entry->router->connection,
699 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
700 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
702 /* If we are router we have to distribute the new Client ID to all
704 if (cmd->server->server_type == SILC_ROUTER && !cmd->server->standalone)
705 silc_server_send_replace_id(server, server->id_entry->router->connection,
707 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
708 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
710 /* Remove old cache entry */
711 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
714 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
718 memset(client->id, 0, SILC_ID_CLIENT_LEN);
719 silc_free(client->id);
722 /* Save the nickname as this client is our local client */
723 if (client->nickname)
724 silc_free(client->nickname);
726 client->nickname = strdup(nick);
729 /* Update client cache */
730 silc_idcache_add(server->local_list->clients, client->nickname,
731 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
733 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
735 /* Send NICK_CHANGE notify */
736 silc_server_send_notify_on_channels(server, client,
737 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
738 oidp->data, oidp->len,
739 nidp->data, nidp->len);
741 /* Send the new Client ID as reply command back to client */
742 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
743 SILC_STATUS_OK, 0, 1,
744 2, nidp->data, nidp->len);
745 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
746 0, packet->data, packet->len, FALSE);
748 silc_buffer_free(packet);
749 silc_buffer_free(nidp);
750 silc_buffer_free(oidp);
753 silc_server_command_free(cmd);
756 SILC_SERVER_CMD_FUNC(list)
760 /* Server side of TOPIC command. Sets topic for channel and/or returns
761 current topic to client. */
763 SILC_SERVER_CMD_FUNC(topic)
765 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
766 SilcServer server = cmd->server;
767 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
768 SilcChannelID *channel_id;
769 SilcChannelEntry channel;
770 SilcChannelClientEntry chl;
771 SilcBuffer packet, idp;
773 unsigned int argc, tmp_len;
775 /* Check number of arguments */
776 argc = silc_argument_get_arg_num(cmd->args);
778 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
779 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
784 SILC_STATUS_ERR_TOO_MANY_PARAMS);
789 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
791 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
792 SILC_STATUS_ERR_NO_CHANNEL_ID);
795 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
797 /* Check whether the channel exists */
798 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
801 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
807 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
810 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
814 if (strlen(tmp) > 256) {
815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
816 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
820 /* See whether has rights to change topic */
821 silc_list_start(channel->user_list);
822 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
823 if (chl->client == client) {
824 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
825 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
826 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
834 /* Set the topic for channel */
836 silc_free(channel->topic);
837 channel->topic = strdup(tmp);
839 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
841 /* Send notify about topic change to all clients on the channel */
842 silc_server_send_notify_to_channel(server, channel,
843 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
845 channel->topic, strlen(channel->topic));
846 silc_buffer_free(idp);
849 /* Send the topic to client as reply packet */
850 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
852 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
853 SILC_STATUS_OK, 0, 2,
854 2, idp->data, idp->len,
856 strlen(channel->topic));
858 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
859 SILC_STATUS_OK, 0, 1,
860 2, idp->data, idp->len);
861 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
862 0, packet->data, packet->len, FALSE);
864 silc_buffer_free(packet);
865 silc_buffer_free(idp);
866 silc_free(channel_id);
869 silc_server_command_free(cmd);
872 /* Server side of INVITE command. Invites some client to join some channel. */
874 SILC_SERVER_CMD_FUNC(invite)
876 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
877 SilcServer server = cmd->server;
878 SilcSocketConnection sock = cmd->sock, dest_sock;
879 SilcClientEntry sender, dest;
880 SilcClientID *dest_id;
881 SilcChannelEntry channel;
882 SilcChannelID *channel_id;
885 unsigned int argc, len;
887 /* Check number of arguments */
888 argc = silc_argument_get_arg_num(cmd->args);
890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
891 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
895 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
896 SILC_STATUS_ERR_TOO_MANY_PARAMS);
900 /* Get destination ID */
901 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
904 SILC_STATUS_ERR_NO_CLIENT_ID);
907 dest_id = silc_id_payload_parse_id(tmp, len);
910 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
912 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
913 SILC_STATUS_ERR_NO_CHANNEL_ID);
916 channel_id = silc_id_payload_parse_id(tmp, len);
918 /* Check whether the channel exists */
919 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
921 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
922 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
926 /* Check whether the sender of this command is on the channel. */
927 sender = (SilcClientEntry)sock->user_data;
928 if (!silc_server_client_on_channel(sender, channel)) {
929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
930 SILC_STATUS_ERR_NOT_ON_CHANNEL);
934 /* Check whether the channel is invite-only channel. If yes then the
935 sender of this command must be at least channel operator. */
936 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
937 SilcChannelClientEntry chl;
939 silc_list_start(channel->user_list);
940 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
941 if (chl->client == sender) {
942 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
944 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
951 /* Find the connection data for the destination. If it is local we will
952 send it directly otherwise we will send it to router for routing. */
953 dest = silc_idlist_find_client_by_id(server->local_list, dest_id);
955 dest_sock = (SilcSocketConnection)dest->connection;
957 dest_sock = silc_server_get_route(server, dest_id, SILC_ID_CLIENT);
959 /* Check whether the requested client is already on the channel. */
960 /* XXX if we are normal server we don't know about global clients on
961 the channel thus we must request it (NAMES command), check from
962 local cache as well. */
963 if (silc_server_client_on_channel(dest, channel)) {
964 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
965 SILC_STATUS_ERR_USER_ON_CHANNEL);
969 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
971 /* Send notify to the client that is invited to the channel */
972 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
973 SILC_NOTIFY_TYPE_INVITE, 2,
974 sidp->data, sidp->len, tmp, len);
976 /* Send command reply */
977 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
980 silc_buffer_free(sidp);
983 silc_server_command_free(cmd);
986 /* Quits connection to client. This gets called if client won't
987 close the connection even when it has issued QUIT command. */
989 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
991 SilcServer server = (SilcServer)context;
992 SilcSocketConnection sock = server->sockets[fd];
994 /* Free all client specific data, such as client entry and entires
995 on channels this client may be on. */
996 silc_server_free_sock_user_data(server, sock);
998 /* Close the connection on our side */
999 silc_server_close_connection(server, sock);
1002 /* Quits SILC session. This is the normal way to disconnect client. */
1004 SILC_SERVER_CMD_FUNC(quit)
1006 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1007 SilcServer server = cmd->server;
1008 SilcSocketConnection sock = cmd->sock;
1010 SILC_LOG_DEBUG(("Start"));
1012 /* We quit the connection with little timeout */
1013 silc_task_register(server->timeout_queue, sock->sock,
1014 silc_server_command_quit_cb, server,
1015 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1017 silc_server_command_free(cmd);
1020 SILC_SERVER_CMD_FUNC(kill)
1024 /* Server side of command INFO. This sends information about us to
1025 the client. If client requested specific server we will send the
1026 command to that server. */
1028 SILC_SERVER_CMD_FUNC(info)
1030 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1031 SilcServer server = cmd->server;
1032 SilcBuffer packet, idp;
1034 char info_string[256], *dest_server;
1036 argc = silc_argument_get_arg_num(cmd->args);
1038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1039 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1044 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1048 /* Get server name */
1049 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1052 SILC_STATUS_ERR_NO_SUCH_SERVER);
1056 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1057 /* Send our reply */
1058 memset(info_string, 0, sizeof(info_string));
1059 snprintf(info_string, sizeof(info_string),
1060 "location: %s server: %s admin: %s <%s>",
1061 server->config->admin_info->location,
1062 server->config->admin_info->server_type,
1063 server->config->admin_info->admin_name,
1064 server->config->admin_info->admin_email);
1066 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1068 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1069 SILC_STATUS_OK, 0, 2,
1070 2, idp->data, idp->len,
1072 strlen(info_string));
1073 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1074 packet->data, packet->len, FALSE);
1076 silc_buffer_free(packet);
1077 silc_buffer_free(idp);
1079 /* Send this command to the requested server */
1081 if (server->server_type == SILC_SERVER && !server->standalone) {
1085 if (server->server_type == SILC_ROUTER) {
1091 silc_server_command_free(cmd);
1094 SILC_SERVER_CMD_FUNC(connect)
1098 /* Server side of command PING. This just replies to the ping. */
1100 SILC_SERVER_CMD_FUNC(ping)
1102 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1103 SilcServer server = cmd->server;
1105 unsigned int argc, len;
1108 argc = silc_argument_get_arg_num(cmd->args);
1110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1111 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1116 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1121 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1123 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1124 SILC_STATUS_ERR_NO_SERVER_ID);
1127 id = silc_id_payload_parse_id(tmp, len);
1129 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1130 /* Send our reply */
1131 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1134 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1135 SILC_STATUS_ERR_NO_SUCH_SERVER);
1142 silc_server_command_free(cmd);
1145 SILC_SERVER_CMD_FUNC(oper)
1154 SilcChannelEntry channel;
1156 SilcClientEntry client;
1157 } JoinInternalContext;
1159 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1161 JoinInternalContext *ctx = (JoinInternalContext *)context;
1163 if (ctx->channel->key && ctx->channel->key_len) {
1166 clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1168 silc_server_send_notify_to_channel(ctx->server, ctx->channel,
1169 SILC_NOTIFY_TYPE_JOIN, 1,
1170 clidp->data, clidp->len);
1172 silc_buffer_free(clidp);
1175 silc_task_register(ctx->server->timeout_queue, fd,
1176 silc_server_command_join_notify, context,
1177 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1181 /* Assembles NAMES command and executes it. This is called when client
1182 joins to a channel and we wan't to send NAMES command reply to the
1185 void silc_server_command_send_names(SilcServer server,
1186 SilcSocketConnection sock,
1187 SilcChannelEntry channel)
1189 SilcServerCommandContext cmd;
1190 SilcBuffer buffer, idp;
1192 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1193 buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1194 1, idp->data, idp->len);
1196 cmd = silc_calloc(1, sizeof(*cmd));
1197 cmd->payload = silc_command_payload_parse(buffer);
1198 cmd->args = silc_command_get_args(cmd->payload);
1199 cmd->server = server;
1201 cmd->pending = FALSE;
1203 silc_server_command_names((void *)cmd);
1208 /* Server side of command JOIN. Joins client into requested channel. If
1209 the channel does not exist it will be created. */
1211 SILC_SERVER_CMD_FUNC(join)
1213 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1214 SilcServer server = cmd->server;
1215 SilcSocketConnection sock = cmd->sock;
1216 SilcBuffer buffer = cmd->packet->buffer;
1217 int argc, i, k, tmp_len;
1218 char *tmp, *channel_name = NULL, *cipher = NULL;
1219 unsigned char *passphrase = NULL, mode[4];
1220 unsigned int umode = 0;
1221 SilcChannelEntry channel;
1222 SilcChannelClientEntry chl;
1223 SilcServerID *router_id;
1224 SilcBuffer packet, idp;
1225 SilcClientEntry client;
1227 SILC_LOG_DEBUG(("Start"));
1229 /* Check number of parameters */
1230 argc = silc_argument_get_arg_num(cmd->args);
1232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1233 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1237 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1238 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1242 /* Get channel name */
1243 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1245 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1246 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1251 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1253 SILC_STATUS_ERR_BAD_CHANNEL);
1254 silc_free(channel_name);
1258 /* Get passphrase */
1259 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1261 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1262 memcpy(passphrase, tmp, tmp_len);
1265 /* Get cipher name */
1266 cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1268 /* See if the channel exists */
1270 silc_idlist_find_channel_by_name(server->local_list, channel_name);
1272 /* Channel not found */
1274 /* If we are standalone server we don't have a router, we just create
1275 the channel by ourselves. */
1276 if (server->standalone) {
1277 router_id = server->id;
1278 channel = silc_server_new_channel(server, router_id, cipher,
1280 umode |= SILC_CHANNEL_UMODE_CHANOP;
1281 umode |= SILC_CHANNEL_UMODE_CHANFO;
1288 /* No channel ID found, the channel does not exist on our server.
1289 We send JOIN command to our router which will handle the joining
1290 procedure (either creates the channel if it doesn't exist or
1291 joins the client to it) - if we are normal server. */
1292 if (server->server_type == SILC_SERVER) {
1294 /* Forward the original JOIN command to the router */
1295 silc_buffer_push(buffer, buffer->data - buffer->head);
1296 silc_server_packet_forward(server, (SilcSocketConnection)
1297 server->id_entry->router->connection,
1298 buffer->data, buffer->len, TRUE);
1300 /* Add the command to be pending. It will be re-executed after
1301 router has replied back to us. */
1302 cmd->pending = TRUE;
1303 silc_server_command_pending(SILC_COMMAND_JOIN, 0,
1304 silc_server_command_join, context);
1309 /* If we are router and the channel does not exist we will check our
1310 global list for the channel. */
1311 if (!channel && server->server_type == SILC_ROUTER) {
1313 /* Notify all routers about the new channel in SILC network. */
1314 if (!server->standalone) {
1316 silc_server_send_new_id(server, server->id_entry->router->connection,
1318 xxx, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN);
1327 * Check channel modes
1330 /* Check invite list if channel is invite-only channel */
1331 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1332 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1333 /* Invite list is specified. Check whether client is invited in the
1334 list. If not, then check whether it has been invited otherwise. */
1337 /* XXX client must be invited to be able to join the channel */
1341 /* Check ban list if set */
1342 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1346 /* Check the channel passphrase if set. */
1347 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1348 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1349 strlen(channel->mode_data.passphrase))) {
1350 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1351 SILC_STATUS_ERR_BAD_PASSWORD);
1356 /* Check user count limit if set. */
1357 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1358 if (silc_list_count(channel->user_list) + 1 >
1359 channel->mode_data.user_limit) {
1360 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1361 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1367 * Client is allowed to join to the channel. Make it happen.
1370 /* If the JOIN request was forwarded to us we will make a bit slower
1371 query to get the client pointer. Otherwise, we get the client pointer
1373 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1374 client = (SilcClientEntry)sock->user_data;
1376 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1377 client = silc_idlist_find_client_by_id(server->local_list, id);
1385 /* Check whether the client already is on the channel */
1386 if (silc_server_client_on_channel(client, channel)) {
1387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1388 SILC_STATUS_ERR_USER_ON_CHANNEL);
1392 /* Join the client to the channel by adding it to channel's user list.
1393 Add also the channel to client entry's channels list for fast cross-
1395 chl = silc_calloc(1, sizeof(*chl));
1397 chl->client = client;
1398 chl->channel = channel;
1399 silc_list_add(channel->user_list, chl);
1400 silc_list_add(client->channels, chl);
1402 /* Notify router about new user on channel. If we are normal server
1403 we send it to our router, if we are router we send it to our
1405 if (!server->standalone) {
1409 /* Send command reply to the client. Client receives the Channe ID,
1410 channel mode and possibly other information in this reply packet. */
1411 if (!cmd->pending) {
1412 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1413 SILC_PUT32_MSB(channel->mode, mode);
1415 if (!channel->topic)
1417 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1418 SILC_STATUS_OK, 0, 3,
1420 strlen(channel_name),
1421 3, idp->data, idp->len,
1425 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1426 SILC_STATUS_OK, 0, 4,
1428 strlen(channel_name),
1429 3, idp->data, idp->len,
1432 strlen(channel->topic));
1434 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1435 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1436 silc_server_packet_send_dest(cmd->server, cmd->sock,
1437 SILC_PACKET_COMMAND_REPLY, 0,
1438 id, cmd->packet->src_id_type,
1439 packet->data, packet->len, FALSE);
1442 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1443 packet->data, packet->len, FALSE);
1444 silc_buffer_free(packet);
1446 /* Send channel key to the client. Client cannot start transmitting
1447 to the channel until we have sent the key. */
1448 tmp_len = strlen(channel->channel_key->cipher->name);
1450 silc_channel_key_payload_encode(idp->len, idp->data,
1451 strlen(channel->channel_key->
1453 channel->channel_key->cipher->name,
1454 channel->key_len / 8, channel->key);
1456 silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
1457 packet->data, packet->len, FALSE);
1459 silc_buffer_free(packet);
1460 silc_buffer_free(idp);
1463 /* Finally, send notify message to all clients on the channel about
1464 new user on the channel. */
1465 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1466 if (!cmd->pending) {
1469 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1471 silc_server_send_notify_to_channel(server, channel,
1472 SILC_NOTIFY_TYPE_JOIN, 1,
1473 clidp->data, clidp->len);
1475 silc_buffer_free(clidp);
1477 /* This is pending command request. Send the notify after we have
1478 received the key for the channel from the router. */
1479 JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
1480 ctx->channel_name = channel_name;
1481 ctx->nickname = client->nickname;
1482 ctx->username = client->username;
1483 ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
1484 ctx->channel = channel;
1485 ctx->server = server;
1486 ctx->client = client;
1487 silc_task_register(server->timeout_queue, sock->sock,
1488 silc_server_command_join_notify, ctx,
1489 0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1493 /* Send NAMES command reply to the joined channel so the user sees who
1494 is currently on the channel. */
1495 silc_server_command_send_names(server, sock, channel);
1498 silc_server_command_free(cmd);
1501 /* Server side of command MOTD. Sends server's current "message of the
1502 day" to the client. */
1504 SILC_SERVER_CMD_FUNC(motd)
1506 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1507 SilcServer server = cmd->server;
1512 SILC_LOG_DEBUG(("Start"));
1514 argc = silc_argument_get_arg_num(cmd->args);
1516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1517 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1521 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1522 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1526 /* XXX show currently only our motd */
1528 if (server->config && server->config->motd &&
1529 server->config->motd->motd_file) {
1532 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
1537 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
1543 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
1548 silc_server_command_free(cmd);
1551 SILC_SERVER_CMD_FUNC(umode)
1555 /* Checks that client has rights to add or remove channel modes. If any
1556 of the checks fails FALSE is returned. */
1558 int silc_server_check_cmode_rights(SilcChannelEntry channel,
1559 SilcChannelClientEntry client,
1562 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1563 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1565 /* Check whether has rights to change anything */
1566 if (!is_op && !is_fo)
1569 /* Check whether has rights to change everything */
1573 /* We know that client is channel operator, check that they are not
1574 changing anything that requires channel founder rights. Rest of the
1575 modes are available automatically for channel operator. */
1577 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1578 if (is_op && !is_fo)
1581 if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
1582 if (is_op && !is_fo)
1587 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1588 if (is_op && !is_fo)
1591 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1592 if (is_op && !is_fo)
1597 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1598 if (is_op && !is_fo)
1601 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1602 if (is_op && !is_fo)
1610 /* Server side command of CMODE. Changes channel mode */
1612 SILC_SERVER_CMD_FUNC(cmode)
1614 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1615 SilcServer server = cmd->server;
1616 SilcSocketConnection sock = cmd->sock;
1617 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1618 SilcChannelID *channel_id;
1619 SilcClientID *client_id;
1620 SilcChannelEntry channel;
1621 SilcChannelClientEntry chl;
1622 SilcBuffer packet, cidp;
1623 unsigned char *tmp, *tmp_id, *tmp_mask;
1624 unsigned int argc, mode_mask, tmp_len, tmp_len2;
1627 SILC_LOG_DEBUG(("Start"));
1629 argc = silc_argument_get_arg_num(cmd->args);
1631 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1632 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1637 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1641 /* Get Channel ID */
1642 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
1644 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1645 SILC_STATUS_ERR_NO_CHANNEL_ID);
1648 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
1650 /* Get the channel mode mask */
1651 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1653 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1654 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1657 SILC_GET32_MSB(mode_mask, tmp_mask);
1659 /* Get channel entry */
1660 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1662 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1663 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1667 /* Check whether this client is on the channel */
1668 if (!silc_server_client_on_channel(client, channel)) {
1669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1670 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1674 /* Get entry to the channel user list */
1675 silc_list_start(channel->user_list);
1676 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1677 if (chl->client == client)
1680 /* Check that client has rights to change any requested channel modes */
1681 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
1682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1683 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1688 * Check the modes. Modes that requires nothing special operation are
1692 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
1693 /* Channel uses private keys to protect traffic. Client(s) has set the
1694 key locally they want to use, server does not know that key. */
1695 /* Nothing interesting to do here now */
1697 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1698 /* The mode is removed and we need to generate and distribute
1699 new channel key. Clients are not using private channel keys
1700 anymore after this. */
1701 unsigned int key_len;
1702 unsigned char channel_key[32];
1704 /* XXX Duplicated code, make own function for this!! LEAVE uses this
1707 /* Re-generate channel key */
1708 key_len = channel->key_len / 8;
1709 for (i = 0; i < key_len; i++)
1710 channel_key[i] = silc_rng_get_byte(server->rng);
1711 channel->channel_key->cipher->set_key(channel->channel_key->context,
1712 channel_key, key_len);
1713 memset(channel->key, 0, key_len);
1714 silc_free(channel->key);
1715 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1716 memcpy(channel->key, channel_key, key_len);
1717 memset(channel_key, 0, sizeof(channel_key));
1719 /* Encode channel key payload to be distributed on the channel */
1721 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1722 strlen(channel->channel_key->
1724 channel->channel_key->cipher->name,
1725 key_len, channel->key);
1727 /* If we are normal server then we will send it to our router. If we
1728 are router we will send it to all local servers that has clients on
1730 if (server->server_type == SILC_SERVER) {
1731 if (!server->standalone)
1732 silc_server_packet_send(server,
1733 cmd->server->id_entry->router->connection,
1734 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1740 /* Send to locally connected clients on the channel */
1741 silc_server_packet_send_local_channel(server, channel,
1742 SILC_PACKET_CHANNEL_KEY, 0,
1743 packet->data, packet->len, FALSE);
1744 silc_buffer_free(packet);
1748 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
1749 /* User limit is set on channel */
1750 unsigned int user_limit;
1752 /* Get user limit */
1753 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1755 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
1756 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1757 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1761 SILC_GET32_MSB(user_limit, tmp);
1762 channel->mode_data.user_limit = user_limit;
1765 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
1766 /* User limit mode is unset. Remove user limit */
1767 channel->mode_data.user_limit = 0;
1770 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
1771 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1772 /* Passphrase has been set to channel */
1774 /* Get the passphrase */
1775 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1777 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1778 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1782 /* Save the passphrase */
1783 channel->mode_data.passphrase = strdup(tmp);
1786 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1787 /* Passphrase mode is unset. remove the passphrase */
1788 if (channel->mode_data.passphrase) {
1789 silc_free(channel->mode_data.passphrase);
1790 channel->mode_data.passphrase = NULL;
1795 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
1796 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
1797 /* Ban list is specified for channel */
1800 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1802 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1803 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1807 /* XXX check that channel founder is not banned */
1809 /* Save the ban list */
1810 channel->mode_data.ban_list = strdup(tmp);
1813 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1814 /* Ban mode is unset. Remove the entire ban list */
1815 if (channel->mode_data.ban_list) {
1816 silc_free(channel->mode_data.ban_list);
1817 channel->mode_data.ban_list = NULL;
1822 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
1823 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
1824 /* Invite list is specified for channel */
1826 /* Get invite list */
1827 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1829 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1830 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1834 /* Save the invite linst */
1835 channel->mode_data.invite_list = strdup(tmp);
1838 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1839 /* Invite list mode is unset. Remove the entire invite list */
1840 if (channel->mode_data.invite_list) {
1841 silc_free(channel->mode_data.invite_list);
1842 channel->mode_data.invite_list = NULL;
1847 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
1848 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1849 /* Cipher to use protect the traffic */
1850 unsigned int key_len = 128;
1851 unsigned char channel_key[32];
1855 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
1857 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1858 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1862 cp = strchr(tmp, ':');
1868 /* XXX Duplicated code, make own function for this!! */
1870 /* Delete old cipher and allocate the new one */
1871 silc_cipher_free(channel->channel_key);
1872 silc_cipher_alloc(tmp, &channel->channel_key);
1874 /* Re-generate channel key */
1876 if (key_len > sizeof(channel_key))
1877 key_len = sizeof(channel_key);
1879 for (i = 0; i < key_len; i++)
1880 channel_key[i] = silc_rng_get_byte(server->rng);
1881 channel->channel_key->cipher->set_key(channel->channel_key->context,
1882 channel_key, key_len);
1883 memset(channel->key, 0, key_len);
1884 silc_free(channel->key);
1885 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1886 memcpy(channel->key, channel_key, key_len);
1887 memset(channel_key, 0, sizeof(channel_key));
1889 /* Encode channel key payload to be distributed on the channel */
1891 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1892 strlen(channel->channel_key->
1894 channel->channel_key->cipher->name,
1895 key_len, channel->key);
1897 /* If we are normal server then we will send it to our router. If we
1898 are router we will send it to all local servers that has clients on
1900 if (server->server_type == SILC_SERVER) {
1901 if (!server->standalone)
1902 silc_server_packet_send(server,
1903 cmd->server->id_entry->router->connection,
1904 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1910 /* Send to locally connected clients on the channel */
1911 silc_server_packet_send_local_channel(server, channel,
1912 SILC_PACKET_CHANNEL_KEY, 0,
1913 packet->data, packet->len, FALSE);
1914 silc_buffer_free(packet);
1917 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1918 /* Cipher mode is unset. Remove the cipher and revert back to
1920 unsigned int key_len;
1921 unsigned char channel_key[32];
1923 if (channel->mode_data.cipher) {
1924 silc_free(channel->mode_data.cipher);
1925 channel->mode_data.cipher = NULL;
1926 channel->mode_data.key_len = 0;
1929 /* Generate new cipher and key for the channel */
1931 /* XXX Duplicated code, make own function for this!! */
1933 /* Delete old cipher and allocate default one */
1934 silc_cipher_free(channel->channel_key);
1935 if (!channel->cipher)
1936 silc_cipher_alloc("twofish", &channel->channel_key);
1938 silc_cipher_alloc(channel->cipher, &channel->channel_key);
1940 /* Re-generate channel key */
1941 key_len = channel->key_len / 8;
1942 for (i = 0; i < key_len; i++)
1943 channel_key[i] = silc_rng_get_byte(server->rng);
1944 channel->channel_key->cipher->set_key(channel->channel_key->context,
1945 channel_key, key_len);
1946 memset(channel->key, 0, key_len);
1947 silc_free(channel->key);
1948 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1949 memcpy(channel->key, channel_key, key_len);
1950 memset(channel_key, 0, sizeof(channel_key));
1952 /* Encode channel key payload to be distributed on the channel */
1954 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1955 strlen(channel->channel_key->
1957 channel->channel_key->cipher->name,
1958 key_len, channel->key);
1960 /* If we are normal server then we will send it to our router. If we
1961 are router we will send it to all local servers that has clients on
1963 if (server->server_type == SILC_SERVER) {
1964 if (!server->standalone)
1965 silc_server_packet_send(server,
1966 cmd->server->id_entry->router->connection,
1967 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1973 /* Send to locally connected clients on the channel */
1974 silc_server_packet_send_local_channel(server, channel,
1975 SILC_PACKET_CHANNEL_KEY, 0,
1976 packet->data, packet->len, FALSE);
1977 silc_buffer_free(packet);
1981 /* Finally, set the mode */
1982 channel->mode = mode_mask;
1984 /* Send CMODE_CHANGE notify */
1985 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1986 silc_server_send_notify_to_channel(server, channel,
1987 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
1988 cidp->data, cidp->len,
1992 /* Send command reply to sender */
1993 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
1994 SILC_STATUS_OK, 0, 1,
1996 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1997 packet->data, packet->len, FALSE);
1999 silc_buffer_free(packet);
2000 silc_free(channel_id);
2003 silc_server_command_free(cmd);
2006 /* Server side of CUMODE command. Changes client's mode on a channel. */
2008 SILC_SERVER_CMD_FUNC(cumode)
2010 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2011 SilcServer server = cmd->server;
2012 SilcSocketConnection sock = cmd->sock;
2013 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2014 SilcChannelID *channel_id;
2015 SilcClientID *client_id;
2016 SilcChannelEntry channel;
2017 SilcClientEntry target_client;
2018 SilcChannelClientEntry chl;
2019 SilcBuffer packet, idp;
2020 unsigned char *tmp, *tmp_id, *tmp_mask;
2021 unsigned int argc, target_mask, sender_mask, tmp_len;
2022 int i, notify = FALSE;
2024 SILC_LOG_DEBUG(("Start"));
2026 argc = silc_argument_get_arg_num(cmd->args);
2028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2029 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2033 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2034 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2038 /* Get Channel ID */
2039 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2041 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2042 SILC_STATUS_ERR_NO_CHANNEL_ID);
2045 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2047 /* Get channel entry */
2048 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
2050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2051 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2055 /* Check whether sender is on the channel */
2056 if (!silc_server_client_on_channel(client, channel)) {
2057 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2058 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2062 /* Check that client has rights to change other's rights */
2063 silc_list_start(channel->user_list);
2064 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2065 if (chl->client == client) {
2066 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2067 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2068 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2069 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2073 sender_mask = chl->mode;
2078 /* Get the target client's channel mode mask */
2079 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2082 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2085 SILC_GET32_MSB(target_mask, tmp_mask);
2087 /* Get target Client ID */
2088 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2090 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2091 SILC_STATUS_ERR_NO_CHANNEL_ID);
2094 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2096 /* Get target client's entry */
2097 target_client = silc_idlist_find_client_by_id(server->local_list, client_id);
2099 /* XXX If target client is not one of mine send to primary route */
2102 /* Check whether target client is on the channel */
2103 if (!silc_server_client_on_channel(target_client, channel)) {
2104 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2105 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2109 /* Get entry to the channel user list */
2110 silc_list_start(channel->user_list);
2111 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2112 if (chl->client == target_client)
2119 /* If the target client is founder, no one else can change their mode
2121 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2122 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2123 SILC_STATUS_ERR_NOT_YOU);
2127 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2128 /* Cannot promote anyone to channel founder */
2129 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2130 SILC_STATUS_ERR_NOT_YOU);
2133 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2134 if (target_client == client) {
2135 /* Remove channel founder rights from itself */
2136 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2139 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2140 SILC_STATUS_ERR_NOT_YOU);
2146 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2147 /* Promote to operator */
2148 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2149 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2153 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2154 /* Demote to normal user */
2155 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2160 /* Send notify to channel, notify only if mode was actually changed. */
2162 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2163 silc_server_send_notify_to_channel(server, channel,
2164 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2165 idp->data, idp->len,
2166 tmp_mask, 4, tmp_id, tmp_len);
2167 silc_buffer_free(idp);
2170 /* Send command reply to sender */
2171 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2172 SILC_STATUS_OK, 0, 2,
2174 3, tmp_id, tmp_len);
2175 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2176 packet->data, packet->len, FALSE);
2178 silc_buffer_free(packet);
2179 silc_free(channel_id);
2180 silc_free(client_id);
2183 silc_server_command_free(cmd);
2186 /* Server side of KICK command. Kicks client out of channel. */
2188 SILC_SERVER_CMD_FUNC(kick)
2190 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2191 SilcServer server = cmd->server;
2192 SilcSocketConnection sock = cmd->sock;
2193 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2197 SILC_SERVER_CMD_FUNC(restart)
2201 SILC_SERVER_CMD_FUNC(close)
2205 SILC_SERVER_CMD_FUNC(die)
2209 SILC_SERVER_CMD_FUNC(silcoper)
2213 /* Server side command of LEAVE. Removes client from a channel. */
2215 SILC_SERVER_CMD_FUNC(leave)
2217 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2218 SilcServer server = cmd->server;
2219 SilcSocketConnection sock = cmd->sock;
2220 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2222 SilcChannelEntry channel;
2224 unsigned int i, argc, key_len, len;
2225 unsigned char *tmp, channel_key[32];
2227 SILC_LOG_DEBUG(("Start"));
2229 argc = silc_argument_get_arg_num(cmd->args);
2231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2232 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2236 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2237 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2241 /* Get Channel ID */
2242 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2245 SILC_STATUS_ERR_NO_CHANNEL_ID);
2248 id = silc_id_payload_parse_id(tmp, len);
2250 /* Get channel entry */
2251 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2253 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2254 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2258 /* Check whether this client is on the channel */
2259 if (!silc_server_client_on_channel(id_entry, channel)) {
2260 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2261 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2265 /* Notify routers that they should remove this client from their list
2266 of clients on the channel. */
2267 if (!server->standalone)
2268 silc_server_send_remove_channel_user(server,
2269 server->id_entry->router->connection,
2270 server->server_type == SILC_ROUTER ?
2271 TRUE : FALSE, id_entry->id, id);
2273 /* Remove client from channel */
2274 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2279 /* If the channel does not exist anymore we won't send anything */
2283 /* Re-generate channel key */
2284 key_len = channel->key_len / 8;
2285 for (i = 0; i < key_len; i++)
2286 channel_key[i] = silc_rng_get_byte(server->rng);
2287 channel->channel_key->cipher->set_key(channel->channel_key->context,
2288 channel_key, key_len);
2289 memset(channel->key, 0, key_len);
2290 silc_free(channel->key);
2291 channel->key = silc_calloc(key_len, sizeof(*channel->key));
2292 memcpy(channel->key, channel_key, key_len);
2293 memset(channel_key, 0, sizeof(channel_key));
2295 /* Encode channel key payload to be distributed on the channel */
2297 silc_channel_key_payload_encode(len, tmp,
2298 strlen(channel->channel_key->cipher->name),
2299 channel->channel_key->cipher->name,
2300 key_len, channel->key);
2302 /* If we are normal server then we will send it to our router. If we
2303 are router we will send it to all local servers that has clients on
2305 if (server->server_type == SILC_SERVER) {
2306 if (!server->standalone)
2307 silc_server_packet_send(server,
2308 cmd->server->id_entry->router->connection,
2309 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2315 /* Send to locally connected clients on the channel */
2316 silc_server_packet_send_local_channel(server, channel,
2317 SILC_PACKET_CHANNEL_KEY, 0,
2318 packet->data, packet->len, FALSE);
2320 silc_buffer_free(packet);
2324 silc_server_command_free(cmd);
2327 /* Server side of command NAMES. Resolves clients and their names currently
2328 joined on the requested channel. The name list is sent back to the
2331 SILC_SERVER_CMD_FUNC(names)
2333 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2334 SilcServer server = cmd->server;
2335 SilcChannelEntry channel;
2336 SilcChannelClientEntry chl;
2339 unsigned int i, len, len2, tmp_len, argc;
2341 char *name_list = NULL, *n;
2342 SilcBuffer client_id_list;
2343 SilcBuffer client_mode_list;
2345 SILC_LOG_DEBUG(("Start"));
2347 argc = silc_argument_get_arg_num(cmd->args);
2349 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2350 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2354 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2355 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2359 /* Get Channel ID */
2360 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2362 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2363 SILC_STATUS_ERR_NO_CHANNEL_ID);
2366 id = silc_id_payload_parse_id(tmp, tmp_len);
2368 /* Check whether the channel exists. If we are normal server and the
2369 channel does not exist we will send this same command to our router
2370 which will know if the channel exists. */
2371 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2373 if (server->server_type == SILC_SERVER && !server->standalone) {
2374 /* XXX Send names command */
2376 cmd->pending = TRUE;
2377 silc_server_command_pending(SILC_COMMAND_NAMES, 0,
2378 silc_server_command_names, context);
2382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2383 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2387 /* Assemble the name list now */
2390 silc_list_start(channel->user_list);
2392 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2393 n = chl->client->nickname;
2397 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2398 memcpy(name_list + (len - len2), n, len2);
2401 if (i == silc_list_count(channel->user_list) - 1)
2403 memcpy(name_list + len, ",", 1);
2411 /* Assemble the Client ID list now */
2412 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2413 silc_list_count(channel->user_list));
2414 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2415 silc_list_start(channel->user_list);
2416 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2419 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2420 silc_buffer_format(client_id_list,
2421 SILC_STR_UI_XNSTRING(idp->data, idp->len),
2423 silc_buffer_pull(client_id_list, idp->len);
2424 silc_buffer_free(idp);
2426 silc_buffer_push(client_id_list,
2427 client_id_list->data - client_id_list->head);
2429 /* Assemble mode list */
2430 client_mode_list = silc_buffer_alloc(4 *
2431 silc_list_count(channel->user_list));
2432 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2433 silc_list_start(channel->user_list);
2434 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2435 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2436 silc_buffer_pull(client_mode_list, 4);
2438 silc_buffer_push(client_mode_list,
2439 client_mode_list->data - client_mode_list->head);
2442 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2443 SILC_STATUS_OK, 0, 4,
2447 4, client_id_list->data,
2448 client_id_list->len,
2449 5, client_mode_list->data,
2450 client_mode_list->len);
2451 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2452 packet->data, packet->len, FALSE);
2454 silc_buffer_free(packet);
2455 silc_free(name_list);
2456 silc_buffer_free(client_id_list);
2457 silc_buffer_free(client_mode_list);
2461 silc_server_command_free(cmd);