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 = silc_packet_context_dup(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);
143 silc_packet_context_free(packet);
147 ctx->args = silc_command_get_args(ctx->payload);
149 /* Execute command. If this fails the packet is dropped. */
150 for (cmd = silc_command_list; cmd->cb; cmd++)
151 if (cmd->cmd == silc_command_get(ctx->payload)) {
153 if (!(cmd->flags & SILC_CF_REG)) {
158 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
165 SILC_LOG_ERROR(("Unknown command, packet dropped"));
166 silc_server_command_free(ctx);
171 /* Add new pending command to be executed when reply to a command has been
172 received. The `reply_cmd' is the command that will call the `callback'
173 with `context' when reply has been received. If `ident' is non-zero
174 the `callback' will be executed when received reply with command
175 identifier `ident'. */
177 void silc_server_command_pending(SilcServer server,
178 SilcCommand reply_cmd,
179 unsigned short ident,
180 SilcCommandCb callback,
183 SilcServerCommandPending *reply;
185 reply = silc_calloc(1, sizeof(*reply));
186 reply->reply_cmd = reply_cmd;
187 reply->ident = ident;
188 reply->context = context;
189 reply->callback = callback;
190 silc_dlist_add(server->pending_commands, reply);
193 /* Deletes pending command by reply command type. */
195 void silc_server_command_pending_del(SilcServer server,
196 SilcCommand reply_cmd,
197 unsigned short ident)
199 SilcServerCommandPending *r;
201 silc_dlist_start(server->pending_commands);
202 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
203 if (r->reply_cmd == reply_cmd && r->ident == ident) {
204 silc_dlist_del(server->pending_commands, r);
210 /* Checks for pending commands and marks callbacks to be called from
211 the command reply function. Returns TRUE if there were pending command. */
213 int silc_server_command_pending_check(SilcServer server,
214 SilcServerCommandReplyContext ctx,
216 unsigned short ident)
218 SilcServerCommandPending *r;
220 silc_dlist_start(server->pending_commands);
221 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
222 if (r->reply_cmd == command && r->ident == ident) {
223 ctx->context = r->context;
224 ctx->callback = r->callback;
233 /* Free's the command context allocated before executing the command */
235 static void silc_server_command_free(SilcServerCommandContext cmd)
239 silc_command_free_payload(cmd->payload);
241 silc_packet_context_free(cmd->packet);
246 /* Sends simple status message as command reply packet */
249 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
251 SilcCommandStatus status)
255 SILC_LOG_DEBUG(("Sending command status %d", status));
257 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
258 silc_server_packet_send(cmd->server, cmd->sock,
259 SILC_PACKET_COMMAND_REPLY, 0,
260 buffer->data, buffer->len, FALSE);
261 silc_buffer_free(buffer);
264 /* Sends command status reply with one extra argument. The argument
265 type must be sent as argument. */
268 silc_server_command_send_status_data(SilcServerCommandContext cmd,
270 SilcCommandStatus status,
271 unsigned int arg_type,
273 unsigned int arg_len)
277 SILC_LOG_DEBUG(("Sending command status %d", status));
279 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
280 arg_type, arg, arg_len);
281 silc_server_packet_send(cmd->server, cmd->sock,
282 SILC_PACKET_COMMAND_REPLY, 0,
283 buffer->data, buffer->len, FALSE);
284 silc_buffer_free(buffer);
287 /* Server side of command WHOIS. Processes user's query and sends found
288 results as command replies back to the client. */
290 SILC_SERVER_CMD_FUNC(whois)
292 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
293 SilcServer server = cmd->server;
294 char *tmp, *nick = NULL, *server_name = NULL;
295 unsigned int i, argc, count = 0, len, clients_count;
297 SilcClientID *client_id = NULL;
298 SilcBuffer packet, idp;
299 SilcClientEntry *clients = NULL, entry;
300 SilcCommandStatus status;
302 SILC_LOG_DEBUG(("Start"));
304 argc = silc_argument_get_arg_num(cmd->args);
306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
307 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
312 SILC_STATUS_ERR_TOO_MANY_PARAMS);
316 /* If client ID is in the command it must be used instead of nickname */
317 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
320 /* No ID, get the nickname@server string and parse it. */
321 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
323 if (strchr(tmp, '@')) {
324 len = strcspn(tmp, "@");
325 nick = silc_calloc(len + 1, sizeof(char));
326 memcpy(nick, tmp, len);
327 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
328 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
334 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
338 /* Command includes ID, use that */
339 client_id = silc_id_payload_parse_id(tmp, len);
343 /* Get the max count of reply messages allowed */
345 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
348 SILC_STATUS_ERR_TOO_MANY_PARAMS);
352 silc_free(server_name);
358 /* Protocol dictates that we must always send the received WHOIS request
359 to our router if we are normal server, so let's do it now unless we
360 are standalone. We will not send any replies to the client until we
361 have received reply from the router. */
362 if (!server->standalone) {
365 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
366 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
368 /* Send WHOIS command to our router */
369 silc_server_packet_send(server, (SilcSocketConnection)
370 server->router->connection,
371 SILC_PACKET_COMMAND, cmd->packet->flags,
372 tmpbuf->data, tmpbuf->len, TRUE);
375 /* We are standalone, let's just do local search and send reply to
376 requesting client. */
378 /* Get all clients matching that nickname */
380 clients = silc_idlist_get_clients_by_nickname(server->local_list,
384 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
386 clients = silc_calloc(1, sizeof(*clients));
392 /* If we are router then we will check our global list as well. */
393 if (server->server_type == SILC_ROUTER) {
395 silc_idlist_find_client_by_nickname(server->global_list,
398 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
399 SILC_STATUS_ERR_NO_SUCH_NICK,
400 3, tmp, strlen(tmp));
407 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
408 SILC_STATUS_ERR_NO_SUCH_NICK,
409 3, tmp, strlen(tmp));
414 /* We are standalone and will send reply to client */
417 status = SILC_STATUS_OK;
418 if (clients_count > 1)
419 status = SILC_STATUS_LIST_START;
421 for (i = 0; i < clients_count; i++) {
424 if (count && i - 1 == count)
427 if (clients_count > 2)
428 status = SILC_STATUS_LIST_ITEM;
430 if (clients_count > 1 && i == clients_count - 1)
431 status = SILC_STATUS_LIST_END;
433 /* Send WHOIS reply */
434 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
435 tmp = silc_argument_get_first_arg(cmd->args, NULL);
438 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
439 char nh[256], uh[256];
440 unsigned char idle[4];
441 SilcSocketConnection hsock;
443 memset(uh, 0, sizeof(uh));
444 memset(nh, 0, sizeof(nh));
446 strncat(nh, entry->nickname, strlen(entry->nickname));
448 len = entry->router ? strlen(entry->router->server_name) :
449 strlen(server->server_name);
450 strncat(nh, entry->router ? entry->router->server_name :
451 server->server_name, len);
453 strncat(uh, entry->username, strlen(entry->username));
455 hsock = (SilcSocketConnection)entry->connection;
456 len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
457 strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
459 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
464 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
466 2, idp->data, idp->len,
470 strlen(entry->userinfo),
474 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
476 2, idp->data, idp->len,
484 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
486 2, idp->data, idp->len,
488 strlen(entry->nickname),
489 4, tmp, strlen(tmp)); /* XXX */
491 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
492 0, packet->data, packet->len, FALSE);
494 silc_buffer_free(packet);
495 silc_buffer_free(idp);
501 silc_free(client_id);
504 silc_server_command_free(cmd);
507 SILC_SERVER_CMD_FUNC(whowas)
511 SILC_SERVER_CMD_FUNC(identify)
513 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
514 SilcServer server = cmd->server;
515 char *tmp, *nick = NULL, *server_name = NULL;
516 unsigned int argc, count = 0, len;
518 SilcClientID *client_id = NULL;
519 SilcClientEntry entry;
520 SilcBuffer packet, idp;
522 SILC_LOG_DEBUG(("Start"));
524 argc = silc_argument_get_arg_num(cmd->args);
526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
527 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
532 SILC_STATUS_ERR_TOO_MANY_PARAMS);
536 /* If client ID is in the command it must be used instead of nickname */
537 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
540 /* Get the nickname@server string and parse it. */
541 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
543 if (strchr(tmp, '@')) {
544 len = strcspn(tmp, "@");
545 nick = silc_calloc(len + 1, sizeof(char));
546 memcpy(nick, tmp, len);
547 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
548 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
553 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
554 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
558 /* Command includes ID, use that */
559 client_id = silc_id_payload_parse_id(tmp, len);
563 /* Get the max count of reply messages allowed */
565 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
567 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
568 SILC_STATUS_ERR_TOO_MANY_PARAMS);
576 entry = silc_idlist_find_client_by_nickname(server->local_list,
579 entry = silc_idlist_find_client_by_hash(server->global_list,
580 nick, server->md5hash);
582 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
585 /* If client was not found and if we are normal server and are connected
586 to a router we will make global query from the router. */
587 if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
589 SilcBuffer buffer = cmd->packet->buffer;
591 SILC_LOG_DEBUG(("Requesting identify from router"));
593 /* Send IDENTIFY command to our router */
594 silc_buffer_push(buffer, buffer->data - buffer->head);
595 silc_server_packet_forward(server, (SilcSocketConnection)
596 server->router->connection,
597 buffer->data, buffer->len, TRUE);
601 /* If we are router we have checked our local list by nickname and our
602 global list by hash so far. It is possible that the client is still not
603 found and we'll check it from local list by hash. */
604 if (!entry && server->server_type == SILC_ROUTER)
605 entry = silc_idlist_find_client_by_hash(server->local_list,
606 nick, server->md5hash);
609 /* The client definitely does not exist */
610 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
611 SILC_STATUS_ERR_NO_SUCH_NICK,
612 3, tmp, strlen(tmp));
616 /* Send IDENTIFY reply */
617 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
618 tmp = silc_argument_get_first_arg(cmd->args, NULL);
619 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
620 SILC_STATUS_OK, 0, 2,
621 2, idp->data, idp->len,
622 3, nick, strlen(nick));
623 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
624 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
625 silc_server_packet_send_dest(server, cmd->sock,
626 SILC_PACKET_COMMAND_REPLY, 0,
627 id, cmd->packet->src_id_type,
628 packet->data, packet->len, FALSE);
631 silc_server_packet_send(server, cmd->sock,
632 SILC_PACKET_COMMAND_REPLY, 0,
633 packet->data, packet->len, FALSE);
636 silc_buffer_free(packet);
637 silc_buffer_free(idp);
639 silc_free(client_id);
645 silc_free(server_name);
646 silc_server_command_free(cmd);
649 /* Checks string for bad characters and returns TRUE if they are found. */
651 static int silc_server_command_bad_chars(char *nick)
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;
660 if (strchr(nick, '@')) return TRUE;
665 /* Server side of command NICK. Sets nickname for user. Setting
666 nickname causes generation of a new client ID for the client. The
667 new client ID is sent to the client after changing the nickname. */
669 SILC_SERVER_CMD_FUNC(nick)
671 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
672 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
673 SilcServer server = cmd->server;
674 SilcBuffer packet, nidp, oidp;
675 SilcClientID *new_id;
678 SILC_LOG_DEBUG(("Start"));
680 /* Check number of arguments */
681 if (silc_argument_get_arg_num(cmd->args) < 1) {
682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
683 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
688 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
689 if (silc_server_command_bad_chars(nick) == TRUE) {
690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
691 SILC_STATUS_ERR_BAD_NICKNAME);
695 /* Create new Client ID */
696 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
697 cmd->server->md5hash, nick,
700 /* Send notify about nickname change to our router. We send the new
701 ID and ask to replace it with the old one. If we are router the
702 packet is broadcasted. */
703 if (!cmd->server->standalone)
704 silc_server_send_replace_id(server, server->router->connection,
705 server->server_type == SILC_SERVER ?
706 FALSE : TRUE, client->id,
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 /* Send NAMES command reply to the joined channel so the user sees who
1173 is currently on the channel. */
1174 silc_server_command_send_names(ctx->server, ctx->client->connection,
1177 silc_buffer_free(clidp);
1180 silc_task_register(ctx->server->timeout_queue, fd,
1181 silc_server_command_join_notify, context,
1182 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1186 /* Assembles NAMES command and executes it. This is called when client
1187 joins to a channel and we wan't to send NAMES command reply to the
1190 void silc_server_command_send_names(SilcServer server,
1191 SilcSocketConnection sock,
1192 SilcChannelEntry channel)
1194 SilcServerCommandContext cmd;
1195 SilcBuffer buffer, idp;
1197 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1198 buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1199 1, idp->data, idp->len);
1201 cmd = silc_calloc(1, sizeof(*cmd));
1202 cmd->payload = silc_command_payload_parse(buffer);
1203 cmd->args = silc_command_get_args(cmd->payload);
1204 cmd->server = server;
1206 cmd->pending = FALSE;
1208 silc_server_command_names((void *)cmd);
1213 /* Internal routine to join channel. The channel sent to this function
1214 has been either created or resolved from ID lists. This joins the sent
1215 client to the channel. */
1218 silc_server_command_join_channel(SilcServer server,
1219 SilcServerCommandContext cmd,
1220 SilcChannelEntry channel,
1223 SilcSocketConnection sock = cmd->sock;
1225 unsigned int tmp_len;
1226 unsigned char *passphrase = NULL, mode[4];
1227 SilcClientEntry client;
1228 SilcChannelClientEntry chl;
1229 SilcBuffer packet, idp;
1234 /* Get passphrase */
1235 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1237 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1238 memcpy(passphrase, tmp, tmp_len);
1242 * Check channel modes
1245 /* Check invite list if channel is invite-only channel */
1246 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1247 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1248 /* Invite list is specified. Check whether client is invited in the
1249 list. If not, then check whether it has been invited otherwise. */
1252 /* XXX client must be invited to be able to join the channel */
1256 /* Check ban list if set */
1257 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1261 /* Check the channel passphrase if set. */
1262 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1263 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1264 strlen(channel->mode_data.passphrase))) {
1265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1266 SILC_STATUS_ERR_BAD_PASSWORD);
1271 /* Check user count limit if set. */
1272 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1273 if (silc_list_count(channel->user_list) + 1 >
1274 channel->mode_data.user_limit) {
1275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1276 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1282 * Client is allowed to join to the channel. Make it happen.
1285 /* If the JOIN request was forwarded to us we will make a bit slower
1286 query to get the client pointer. Otherwise, we get the client pointer
1288 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1289 client = (SilcClientEntry)sock->user_data;
1291 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1292 client = silc_idlist_find_client_by_id(server->local_list, id);
1295 SILC_LOG_ERROR(("Forwarded join command did not find the client who "
1296 "wanted to join the channel"));
1302 /* Check whether the client already is on the channel */
1303 if (silc_server_client_on_channel(client, channel)) {
1304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1305 SILC_STATUS_ERR_USER_ON_CHANNEL);
1309 /* Join the client to the channel by adding it to channel's user list.
1310 Add also the channel to client entry's channels list for fast cross-
1312 chl = silc_calloc(1, sizeof(*chl));
1314 chl->client = client;
1315 chl->channel = channel;
1316 silc_list_add(channel->user_list, chl);
1317 silc_list_add(client->channels, chl);
1319 /* Notify router about new user on channel. If we are normal server
1320 we send it to our router, if we are router we send it to our
1322 if (!server->standalone) {
1326 /* Send command reply to the client. Client receives the Channe ID,
1327 channel mode and possibly other information in this reply packet. */
1328 if (!cmd->pending) {
1329 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1330 SILC_PUT32_MSB(channel->mode, mode);
1332 if (!channel->topic)
1334 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1335 SILC_STATUS_OK, 0, 3,
1336 2, channel->channel_name,
1337 strlen(channel->channel_name),
1338 3, idp->data, idp->len,
1342 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1343 SILC_STATUS_OK, 0, 4,
1344 2, channel->channel_name,
1345 strlen(channel->channel_name),
1346 3, idp->data, idp->len,
1349 strlen(channel->topic));
1351 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1352 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1353 silc_server_packet_send_dest(cmd->server, cmd->sock,
1354 SILC_PACKET_COMMAND_REPLY, 0,
1355 id, cmd->packet->src_id_type,
1356 packet->data, packet->len, FALSE);
1359 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1360 packet->data, packet->len, FALSE);
1361 silc_buffer_free(packet);
1363 /* Send channel key to the client. Client cannot start transmitting
1364 to the channel until we have sent the key. */
1365 tmp_len = strlen(channel->channel_key->cipher->name);
1367 silc_channel_key_payload_encode(idp->len, idp->data,
1368 strlen(channel->channel_key->
1370 channel->channel_key->cipher->name,
1371 channel->key_len / 8, channel->key);
1373 silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
1374 packet->data, packet->len, FALSE);
1376 silc_buffer_free(packet);
1377 silc_buffer_free(idp);
1380 /* Finally, send notify message to all clients on the channel about
1381 new user on the channel. */
1382 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1383 if (!cmd->pending) {
1386 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1388 silc_server_send_notify_to_channel(server, channel,
1389 SILC_NOTIFY_TYPE_JOIN, 1,
1390 clidp->data, clidp->len);
1392 silc_buffer_free(clidp);
1394 /* This is pending command request. Send the notify after we have
1395 received the key for the channel from the router. */
1396 JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
1397 ctx->channel_name = channel->channel_name;
1398 ctx->nickname = client->nickname;
1399 ctx->username = client->username;
1400 ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
1401 ctx->channel = channel;
1402 ctx->server = server;
1403 ctx->client = client;
1404 silc_task_register(server->timeout_queue, sock->sock,
1405 silc_server_command_join_notify, ctx,
1406 0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1410 /* Send NAMES command reply to the joined channel so the user sees who
1411 is currently on the channel. */
1412 silc_server_command_send_names(server, sock, channel);
1417 silc_free(passphrase);
1420 /* Server side of command JOIN. Joins client into requested channel. If
1421 the channel does not exist it will be created. */
1423 SILC_SERVER_CMD_FUNC(join)
1425 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1426 SilcServer server = cmd->server;
1428 char *tmp, *channel_name = NULL, *cipher = NULL;
1429 SilcChannelEntry channel;
1430 unsigned int umode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
1432 SILC_LOG_DEBUG(("Start"));
1434 /* Check number of parameters */
1435 argc = silc_argument_get_arg_num(cmd->args);
1437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1438 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1443 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1447 /* Get channel name */
1448 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1451 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1456 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1458 SILC_STATUS_ERR_BAD_CHANNEL);
1459 silc_free(channel_name);
1463 /* Get cipher name */
1464 cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1466 /* See if the channel exists */
1467 channel = silc_idlist_find_channel_by_name(server->local_list, channel_name);
1469 /* Channel not found */
1471 /* If we are standalone server we don't have a router, we just create
1472 the channel by ourselves. */
1473 if (server->standalone) {
1474 channel = silc_server_new_channel(server, server->id, cipher,
1478 /* The channel does not exist on our server. We send JOIN command to
1479 our router which will handle the joining procedure (either creates
1480 the channel if it doesn't exist or joins the client to it) - if we
1481 are normal server. */
1482 if (server->server_type == SILC_SERVER) {
1483 SilcBuffer buffer = cmd->packet->buffer;
1485 /* Forward the original JOIN command to the router */
1486 silc_buffer_push(buffer, buffer->data - buffer->head);
1487 silc_server_packet_forward(server, (SilcSocketConnection)
1488 server->router->connection,
1489 buffer->data, buffer->len, TRUE);
1491 /* Add the command to be pending. It will be re-executed after
1492 router has replied back to us. */
1493 cmd->pending = TRUE;
1494 silc_server_command_pending(server, SILC_COMMAND_JOIN, 0,
1495 silc_server_command_join, context);
1499 /* We are router and the channel does not seem exist so we will check
1500 our global list as well for the channel. */
1501 channel = silc_idlist_find_channel_by_name(server->global_list,
1504 /* Channel really does not exist, create it */
1505 channel = silc_server_new_channel(server, server->id, cipher,
1507 umode |= SILC_CHANNEL_UMODE_CHANOP;
1508 umode |= SILC_CHANNEL_UMODE_CHANFO;
1513 /* Join to the channel */
1514 silc_server_command_join_channel(server, cmd, channel, umode);
1517 silc_server_command_free(cmd);
1520 /* Server side of command MOTD. Sends server's current "message of the
1521 day" to the client. */
1523 SILC_SERVER_CMD_FUNC(motd)
1525 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1526 SilcServer server = cmd->server;
1531 SILC_LOG_DEBUG(("Start"));
1533 argc = silc_argument_get_arg_num(cmd->args);
1535 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1536 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1541 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1545 /* XXX show currently only our motd */
1547 if (server->config && server->config->motd &&
1548 server->config->motd->motd_file) {
1551 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
1556 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
1562 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
1567 silc_server_command_free(cmd);
1570 SILC_SERVER_CMD_FUNC(umode)
1574 /* Checks that client has rights to add or remove channel modes. If any
1575 of the checks fails FALSE is returned. */
1577 int silc_server_check_cmode_rights(SilcChannelEntry channel,
1578 SilcChannelClientEntry client,
1581 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1582 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1584 /* Check whether has rights to change anything */
1585 if (!is_op && !is_fo)
1588 /* Check whether has rights to change everything */
1592 /* We know that client is channel operator, check that they are not
1593 changing anything that requires channel founder rights. Rest of the
1594 modes are available automatically for channel operator. */
1596 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1597 if (is_op && !is_fo)
1600 if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
1601 if (is_op && !is_fo)
1606 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1607 if (is_op && !is_fo)
1610 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1611 if (is_op && !is_fo)
1616 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1617 if (is_op && !is_fo)
1620 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1621 if (is_op && !is_fo)
1629 /* Server side command of CMODE. Changes channel mode */
1631 SILC_SERVER_CMD_FUNC(cmode)
1633 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1634 SilcServer server = cmd->server;
1635 SilcSocketConnection sock = cmd->sock;
1636 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1637 SilcChannelID *channel_id;
1638 SilcClientID *client_id;
1639 SilcChannelEntry channel;
1640 SilcChannelClientEntry chl;
1641 SilcBuffer packet, cidp;
1642 unsigned char *tmp, *tmp_id, *tmp_mask;
1643 unsigned int argc, mode_mask, tmp_len, tmp_len2;
1646 SILC_LOG_DEBUG(("Start"));
1648 argc = silc_argument_get_arg_num(cmd->args);
1650 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1651 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1656 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1660 /* Get Channel ID */
1661 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
1663 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1664 SILC_STATUS_ERR_NO_CHANNEL_ID);
1667 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
1669 /* Get the channel mode mask */
1670 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1673 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1676 SILC_GET32_MSB(mode_mask, tmp_mask);
1678 /* Get channel entry */
1679 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1682 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1686 /* Check whether this client is on the channel */
1687 if (!silc_server_client_on_channel(client, channel)) {
1688 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1689 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1693 /* Get entry to the channel user list */
1694 silc_list_start(channel->user_list);
1695 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1696 if (chl->client == client)
1699 /* Check that client has rights to change any requested channel modes */
1700 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
1701 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1702 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1707 * Check the modes. Modes that requires nothing special operation are
1711 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
1712 /* Channel uses private keys to protect traffic. Client(s) has set the
1713 key locally they want to use, server does not know that key. */
1714 /* Nothing interesting to do here now */
1716 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1717 /* The mode is removed and we need to generate and distribute
1718 new channel key. Clients are not using private channel keys
1719 anymore after this. */
1720 unsigned int key_len;
1721 unsigned char channel_key[32];
1723 /* XXX Duplicated code, make own function for this!! LEAVE uses this
1726 /* Re-generate channel key */
1727 key_len = channel->key_len / 8;
1728 for (i = 0; i < key_len; i++)
1729 channel_key[i] = silc_rng_get_byte(server->rng);
1730 channel->channel_key->cipher->set_key(channel->channel_key->context,
1731 channel_key, key_len);
1732 memset(channel->key, 0, key_len);
1733 silc_free(channel->key);
1734 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1735 memcpy(channel->key, channel_key, key_len);
1736 memset(channel_key, 0, sizeof(channel_key));
1738 /* Encode channel key payload to be distributed on the channel */
1740 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1741 strlen(channel->channel_key->
1743 channel->channel_key->cipher->name,
1744 key_len, channel->key);
1746 /* If we are normal server then we will send it to our router. If we
1747 are router we will send it to all local servers that has clients on
1749 if (server->server_type == SILC_SERVER) {
1750 if (!server->standalone)
1751 silc_server_packet_send(server,
1752 cmd->server->router->connection,
1753 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1759 /* Send to locally connected clients on the channel */
1760 silc_server_packet_send_local_channel(server, channel,
1761 SILC_PACKET_CHANNEL_KEY, 0,
1762 packet->data, packet->len, FALSE);
1763 silc_buffer_free(packet);
1767 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
1768 /* User limit is set on channel */
1769 unsigned int user_limit;
1771 /* Get user limit */
1772 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1774 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
1775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1776 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1780 SILC_GET32_MSB(user_limit, tmp);
1781 channel->mode_data.user_limit = user_limit;
1784 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
1785 /* User limit mode is unset. Remove user limit */
1786 channel->mode_data.user_limit = 0;
1789 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
1790 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1791 /* Passphrase has been set to channel */
1793 /* Get the passphrase */
1794 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1797 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1801 /* Save the passphrase */
1802 channel->mode_data.passphrase = strdup(tmp);
1805 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1806 /* Passphrase mode is unset. remove the passphrase */
1807 if (channel->mode_data.passphrase) {
1808 silc_free(channel->mode_data.passphrase);
1809 channel->mode_data.passphrase = NULL;
1814 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
1815 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
1816 /* Ban list is specified for channel */
1819 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1822 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1826 /* XXX check that channel founder is not banned */
1828 /* Save the ban list */
1829 channel->mode_data.ban_list = strdup(tmp);
1832 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1833 /* Ban mode is unset. Remove the entire ban list */
1834 if (channel->mode_data.ban_list) {
1835 silc_free(channel->mode_data.ban_list);
1836 channel->mode_data.ban_list = NULL;
1841 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
1842 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
1843 /* Invite list is specified for channel */
1845 /* Get invite list */
1846 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1849 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1853 /* Save the invite linst */
1854 channel->mode_data.invite_list = strdup(tmp);
1857 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1858 /* Invite list mode is unset. Remove the entire invite list */
1859 if (channel->mode_data.invite_list) {
1860 silc_free(channel->mode_data.invite_list);
1861 channel->mode_data.invite_list = NULL;
1866 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
1867 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1868 /* Cipher to use protect the traffic */
1869 unsigned int key_len = 128;
1870 unsigned char channel_key[32];
1874 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
1876 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1877 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1881 cp = strchr(tmp, ':');
1887 /* XXX Duplicated code, make own function for this!! */
1889 /* Delete old cipher and allocate the new one */
1890 silc_cipher_free(channel->channel_key);
1891 silc_cipher_alloc(tmp, &channel->channel_key);
1893 /* Re-generate channel key */
1895 if (key_len > sizeof(channel_key))
1896 key_len = sizeof(channel_key);
1898 for (i = 0; i < key_len; i++)
1899 channel_key[i] = silc_rng_get_byte(server->rng);
1900 channel->channel_key->cipher->set_key(channel->channel_key->context,
1901 channel_key, key_len);
1902 memset(channel->key, 0, key_len);
1903 silc_free(channel->key);
1904 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1905 memcpy(channel->key, channel_key, key_len);
1906 memset(channel_key, 0, sizeof(channel_key));
1908 /* Encode channel key payload to be distributed on the channel */
1910 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1911 strlen(channel->channel_key->
1913 channel->channel_key->cipher->name,
1914 key_len, channel->key);
1916 /* If we are normal server then we will send it to our router. If we
1917 are router we will send it to all local servers that has clients on
1919 if (server->server_type == SILC_SERVER) {
1920 if (!server->standalone)
1921 silc_server_packet_send(server,
1922 cmd->server->router->connection,
1923 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1929 /* Send to locally connected clients on the channel */
1930 silc_server_packet_send_local_channel(server, channel,
1931 SILC_PACKET_CHANNEL_KEY, 0,
1932 packet->data, packet->len, FALSE);
1933 silc_buffer_free(packet);
1936 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1937 /* Cipher mode is unset. Remove the cipher and revert back to
1939 unsigned int key_len;
1940 unsigned char channel_key[32];
1942 if (channel->mode_data.cipher) {
1943 silc_free(channel->mode_data.cipher);
1944 channel->mode_data.cipher = NULL;
1945 channel->mode_data.key_len = 0;
1948 /* Generate new cipher and key for the channel */
1950 /* XXX Duplicated code, make own function for this!! */
1952 /* Delete old cipher and allocate default one */
1953 silc_cipher_free(channel->channel_key);
1954 if (!channel->cipher)
1955 silc_cipher_alloc("twofish", &channel->channel_key);
1957 silc_cipher_alloc(channel->cipher, &channel->channel_key);
1959 /* Re-generate channel key */
1960 key_len = channel->key_len / 8;
1961 for (i = 0; i < key_len; i++)
1962 channel_key[i] = silc_rng_get_byte(server->rng);
1963 channel->channel_key->cipher->set_key(channel->channel_key->context,
1964 channel_key, key_len);
1965 memset(channel->key, 0, key_len);
1966 silc_free(channel->key);
1967 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1968 memcpy(channel->key, channel_key, key_len);
1969 memset(channel_key, 0, sizeof(channel_key));
1971 /* Encode channel key payload to be distributed on the channel */
1973 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1974 strlen(channel->channel_key->
1976 channel->channel_key->cipher->name,
1977 key_len, channel->key);
1979 /* If we are normal server then we will send it to our router. If we
1980 are router we will send it to all local servers that has clients on
1982 if (server->server_type == SILC_SERVER) {
1983 if (!server->standalone)
1984 silc_server_packet_send(server,
1985 cmd->server->router->connection,
1986 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1992 /* Send to locally connected clients on the channel */
1993 silc_server_packet_send_local_channel(server, channel,
1994 SILC_PACKET_CHANNEL_KEY, 0,
1995 packet->data, packet->len, FALSE);
1996 silc_buffer_free(packet);
2000 /* Finally, set the mode */
2001 channel->mode = mode_mask;
2003 /* Send CMODE_CHANGE notify */
2004 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2005 silc_server_send_notify_to_channel(server, channel,
2006 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2007 cidp->data, cidp->len,
2011 /* Send command reply to sender */
2012 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2013 SILC_STATUS_OK, 0, 1,
2015 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2016 packet->data, packet->len, FALSE);
2018 silc_buffer_free(packet);
2019 silc_free(channel_id);
2022 silc_server_command_free(cmd);
2025 /* Server side of CUMODE command. Changes client's mode on a channel. */
2027 SILC_SERVER_CMD_FUNC(cumode)
2029 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2030 SilcServer server = cmd->server;
2031 SilcSocketConnection sock = cmd->sock;
2032 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2033 SilcChannelID *channel_id;
2034 SilcClientID *client_id;
2035 SilcChannelEntry channel;
2036 SilcClientEntry target_client;
2037 SilcChannelClientEntry chl;
2038 SilcBuffer packet, idp;
2039 unsigned char *tmp, *tmp_id, *tmp_mask;
2040 unsigned int argc, target_mask, sender_mask, tmp_len;
2041 int i, notify = FALSE;
2043 SILC_LOG_DEBUG(("Start"));
2045 argc = silc_argument_get_arg_num(cmd->args);
2047 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2048 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2053 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2057 /* Get Channel ID */
2058 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2060 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2061 SILC_STATUS_ERR_NO_CHANNEL_ID);
2064 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2066 /* Get channel entry */
2067 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
2069 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2070 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2074 /* Check whether sender is on the channel */
2075 if (!silc_server_client_on_channel(client, channel)) {
2076 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2077 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2081 /* Check that client has rights to change other's rights */
2082 silc_list_start(channel->user_list);
2083 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2084 if (chl->client == client) {
2085 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2086 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2087 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2088 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2092 sender_mask = chl->mode;
2097 /* Get the target client's channel mode mask */
2098 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2100 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2101 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2104 SILC_GET32_MSB(target_mask, tmp_mask);
2106 /* Get target Client ID */
2107 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2110 SILC_STATUS_ERR_NO_CHANNEL_ID);
2113 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2115 /* Get target client's entry */
2116 target_client = silc_idlist_find_client_by_id(server->local_list, client_id);
2118 /* XXX If target client is not one of mine send to primary route */
2121 /* Check whether target client is on the channel */
2122 if (!silc_server_client_on_channel(target_client, channel)) {
2123 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2124 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2128 /* Get entry to the channel user list */
2129 silc_list_start(channel->user_list);
2130 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2131 if (chl->client == target_client)
2138 /* If the target client is founder, no one else can change their mode
2140 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2141 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2142 SILC_STATUS_ERR_NOT_YOU);
2146 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2147 /* Cannot promote anyone to channel founder */
2148 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2149 SILC_STATUS_ERR_NOT_YOU);
2152 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2153 if (target_client == client) {
2154 /* Remove channel founder rights from itself */
2155 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2158 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2159 SILC_STATUS_ERR_NOT_YOU);
2165 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2166 /* Promote to operator */
2167 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2168 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2172 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2173 /* Demote to normal user */
2174 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2179 /* Send notify to channel, notify only if mode was actually changed. */
2181 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2182 silc_server_send_notify_to_channel(server, channel,
2183 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2184 idp->data, idp->len,
2185 tmp_mask, 4, tmp_id, tmp_len);
2186 silc_buffer_free(idp);
2189 /* Send command reply to sender */
2190 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2191 SILC_STATUS_OK, 0, 2,
2193 3, tmp_id, tmp_len);
2194 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2195 packet->data, packet->len, FALSE);
2197 silc_buffer_free(packet);
2198 silc_free(channel_id);
2199 silc_free(client_id);
2202 silc_server_command_free(cmd);
2205 /* Server side of KICK command. Kicks client out of channel. */
2207 SILC_SERVER_CMD_FUNC(kick)
2209 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2210 SilcServer server = cmd->server;
2211 SilcSocketConnection sock = cmd->sock;
2212 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2216 SILC_SERVER_CMD_FUNC(restart)
2220 SILC_SERVER_CMD_FUNC(close)
2224 SILC_SERVER_CMD_FUNC(die)
2228 SILC_SERVER_CMD_FUNC(silcoper)
2232 /* Server side command of LEAVE. Removes client from a channel. */
2234 SILC_SERVER_CMD_FUNC(leave)
2236 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2237 SilcServer server = cmd->server;
2238 SilcSocketConnection sock = cmd->sock;
2239 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2241 SilcChannelEntry channel;
2243 unsigned int i, argc, key_len, len;
2244 unsigned char *tmp, channel_key[32];
2246 SILC_LOG_DEBUG(("Start"));
2248 argc = silc_argument_get_arg_num(cmd->args);
2250 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2251 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2255 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2256 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2260 /* Get Channel ID */
2261 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2263 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2264 SILC_STATUS_ERR_NO_CHANNEL_ID);
2267 id = silc_id_payload_parse_id(tmp, len);
2269 /* Get channel entry */
2270 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2273 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2277 /* Check whether this client is on the channel */
2278 if (!silc_server_client_on_channel(id_entry, channel)) {
2279 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2280 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2284 /* Notify routers that they should remove this client from their list
2285 of clients on the channel. */
2286 if (!server->standalone)
2287 silc_server_send_remove_channel_user(server,
2288 server->router->connection,
2289 server->server_type == SILC_ROUTER ?
2290 TRUE : FALSE, id_entry->id, id);
2292 /* Remove client from channel */
2293 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2298 /* If the channel does not exist anymore we won't send anything */
2302 /* Re-generate channel key */
2303 key_len = channel->key_len / 8;
2304 for (i = 0; i < key_len; i++)
2305 channel_key[i] = silc_rng_get_byte(server->rng);
2306 channel->channel_key->cipher->set_key(channel->channel_key->context,
2307 channel_key, key_len);
2308 memset(channel->key, 0, key_len);
2309 silc_free(channel->key);
2310 channel->key = silc_calloc(key_len, sizeof(*channel->key));
2311 memcpy(channel->key, channel_key, key_len);
2312 memset(channel_key, 0, sizeof(channel_key));
2314 /* Encode channel key payload to be distributed on the channel */
2316 silc_channel_key_payload_encode(len, tmp,
2317 strlen(channel->channel_key->cipher->name),
2318 channel->channel_key->cipher->name,
2319 key_len, channel->key);
2321 /* If we are normal server then we will send it to our router. If we
2322 are router we will send it to all local servers that has clients on
2324 if (server->server_type == SILC_SERVER) {
2325 if (!server->standalone)
2326 silc_server_packet_send(server,
2327 cmd->server->router->connection,
2328 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2334 /* Send to locally connected clients on the channel */
2335 silc_server_packet_send_local_channel(server, channel,
2336 SILC_PACKET_CHANNEL_KEY, 0,
2337 packet->data, packet->len, FALSE);
2339 silc_buffer_free(packet);
2343 silc_server_command_free(cmd);
2346 /* Server side of command NAMES. Resolves clients and their names currently
2347 joined on the requested channel. The name list is sent back to the
2350 SILC_SERVER_CMD_FUNC(names)
2352 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2353 SilcServer server = cmd->server;
2354 SilcChannelEntry channel;
2355 SilcChannelClientEntry chl;
2358 unsigned int i, len, len2, tmp_len, argc;
2360 char *name_list = NULL, *n;
2361 SilcBuffer client_id_list;
2362 SilcBuffer client_mode_list;
2364 SILC_LOG_DEBUG(("Start"));
2366 argc = silc_argument_get_arg_num(cmd->args);
2368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2369 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2374 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2378 /* Get Channel ID */
2379 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2381 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2382 SILC_STATUS_ERR_NO_CHANNEL_ID);
2385 id = silc_id_payload_parse_id(tmp, tmp_len);
2387 /* Check whether the channel exists. If we are normal server and the
2388 channel does not exist we will send this same command to our router
2389 which will know if the channel exists. */
2390 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2392 if (server->server_type == SILC_SERVER && !server->standalone) {
2393 /* XXX Send names command */
2395 cmd->pending = TRUE;
2396 silc_server_command_pending(server, SILC_COMMAND_NAMES, 0,
2397 silc_server_command_names, context);
2401 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2402 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2406 /* Assemble the name list now */
2409 silc_list_start(channel->user_list);
2411 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2412 n = chl->client->nickname;
2416 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2417 memcpy(name_list + (len - len2), n, len2);
2420 if (i == silc_list_count(channel->user_list) - 1)
2422 memcpy(name_list + len, ",", 1);
2430 /* Assemble the Client ID list now */
2431 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2432 silc_list_count(channel->user_list));
2433 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2434 silc_list_start(channel->user_list);
2435 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2438 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2439 silc_buffer_format(client_id_list,
2440 SILC_STR_UI_XNSTRING(idp->data, idp->len),
2442 silc_buffer_pull(client_id_list, idp->len);
2443 silc_buffer_free(idp);
2445 silc_buffer_push(client_id_list,
2446 client_id_list->data - client_id_list->head);
2448 /* Assemble mode list */
2449 client_mode_list = silc_buffer_alloc(4 *
2450 silc_list_count(channel->user_list));
2451 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2452 silc_list_start(channel->user_list);
2453 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2454 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2455 silc_buffer_pull(client_mode_list, 4);
2457 silc_buffer_push(client_mode_list,
2458 client_mode_list->data - client_mode_list->head);
2461 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2462 SILC_STATUS_OK, 0, 4,
2466 4, client_id_list->data,
2467 client_id_list->len,
2468 5, client_mode_list->data,
2469 client_mode_list->len);
2470 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2471 packet->data, packet->len, FALSE);
2473 silc_buffer_free(packet);
2474 silc_free(name_list);
2475 silc_buffer_free(client_id_list);
2476 silc_buffer_free(client_mode_list);
2480 silc_server_command_free(cmd);