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, TRUE,
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_str2id(tmp, SILC_ID_SERVER);
1131 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1132 /* Send our reply */
1133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1137 SILC_STATUS_ERR_NO_SUCH_SERVER);
1144 silc_server_command_free(cmd);
1147 SILC_SERVER_CMD_FUNC(oper)
1156 SilcChannelEntry channel;
1158 SilcClientEntry client;
1159 } JoinInternalContext;
1161 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1163 JoinInternalContext *ctx = (JoinInternalContext *)context;
1165 if (ctx->channel->key && ctx->channel->key_len) {
1168 clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1170 silc_server_send_notify_to_channel(ctx->server, ctx->channel, FALSE,
1171 SILC_NOTIFY_TYPE_JOIN, 1,
1172 clidp->data, clidp->len);
1174 /* Send NEW_CHANNEL_USER packet to primary route */
1175 silc_server_send_new_channel_user(server, server->router->connection,
1176 server->server_type == SILC_SERVER ?
1178 channel->id, SILC_ID_CHANNEL_LEN,
1179 client->id, SILC_ID_CLIENT_LEN);
1182 /* Send NAMES command reply to the joined channel so the user sees who
1183 is currently on the channel. */
1184 silc_server_command_send_names(ctx->server, ctx->client->connection,
1187 silc_buffer_free(clidp);
1190 silc_task_register(ctx->server->timeout_queue, fd,
1191 silc_server_command_join_notify, context,
1192 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1196 /* Assembles NAMES command and executes it. This is called when client
1197 joins to a channel and we wan't to send NAMES command reply to the
1200 void silc_server_command_send_names(SilcServer server,
1201 SilcSocketConnection sock,
1202 SilcChannelEntry channel)
1204 SilcServerCommandContext cmd;
1205 SilcBuffer buffer, idp;
1207 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1208 buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1209 1, idp->data, idp->len);
1211 cmd = silc_calloc(1, sizeof(*cmd));
1212 cmd->payload = silc_command_payload_parse(buffer);
1213 cmd->args = silc_command_get_args(cmd->payload);
1214 cmd->server = server;
1216 cmd->pending = FALSE;
1218 silc_server_command_names((void *)cmd);
1223 /* Internal routine to join channel. The channel sent to this function
1224 has been either created or resolved from ID lists. This joins the sent
1225 client to the channel. */
1228 silc_server_command_join_channel(SilcServer server,
1229 SilcServerCommandContext cmd,
1230 SilcChannelEntry channel,
1233 SilcSocketConnection sock = cmd->sock;
1235 unsigned int tmp_len;
1236 unsigned char *passphrase = NULL, mode[4];
1237 SilcClientEntry client;
1238 SilcChannelClientEntry chl;
1239 SilcBuffer packet, idp;
1244 /* Get passphrase */
1245 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1247 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1248 memcpy(passphrase, tmp, tmp_len);
1252 * Check channel modes
1255 /* Check invite list if channel is invite-only channel */
1256 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1257 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1258 /* Invite list is specified. Check whether client is invited in the
1259 list. If not, then check whether it has been invited otherwise. */
1262 /* XXX client must be invited to be able to join the channel */
1266 /* Check ban list if set */
1267 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1271 /* Check the channel passphrase if set. */
1272 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1273 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1274 strlen(channel->mode_data.passphrase))) {
1275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1276 SILC_STATUS_ERR_BAD_PASSWORD);
1281 /* Check user count limit if set. */
1282 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1283 if (silc_list_count(channel->user_list) + 1 >
1284 channel->mode_data.user_limit) {
1285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1286 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1292 * Client is allowed to join to the channel. Make it happen.
1295 /* If the JOIN request was forwarded to us we will make a bit slower
1296 query to get the client pointer. Otherwise, we get the client pointer
1298 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1299 client = (SilcClientEntry)sock->user_data;
1301 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1302 client = silc_idlist_find_client_by_id(server->local_list, id);
1305 SILC_LOG_ERROR(("Forwarded join command did not find the client who "
1306 "wanted to join the channel"));
1312 /* Check whether the client already is on the channel */
1313 if (silc_server_client_on_channel(client, channel)) {
1314 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1315 SILC_STATUS_ERR_USER_ON_CHANNEL);
1319 /* Join the client to the channel by adding it to channel's user list.
1320 Add also the channel to client entry's channels list for fast cross-
1322 chl = silc_calloc(1, sizeof(*chl));
1324 chl->client = client;
1325 chl->channel = channel;
1326 silc_list_add(channel->user_list, chl);
1327 silc_list_add(client->channels, chl);
1329 /* Notify router about new user on channel. If we are normal server
1330 we send it to our router, if we are router we send it to our
1332 if (!server->standalone) {
1336 /* Send command reply to the client. Client receives the Channe ID,
1337 channel mode and possibly other information in this reply packet. */
1338 if (!cmd->pending) {
1339 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1340 SILC_PUT32_MSB(channel->mode, mode);
1342 if (!channel->topic)
1344 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1345 SILC_STATUS_OK, 0, 3,
1346 2, channel->channel_name,
1347 strlen(channel->channel_name),
1348 3, idp->data, idp->len,
1352 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1353 SILC_STATUS_OK, 0, 4,
1354 2, channel->channel_name,
1355 strlen(channel->channel_name),
1356 3, idp->data, idp->len,
1359 strlen(channel->topic));
1361 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1362 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1363 silc_server_packet_send_dest(cmd->server, cmd->sock,
1364 SILC_PACKET_COMMAND_REPLY, 0,
1365 id, cmd->packet->src_id_type,
1366 packet->data, packet->len, FALSE);
1369 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1370 packet->data, packet->len, FALSE);
1371 silc_buffer_free(packet);
1373 /* Send channel key to the client. Client cannot start transmitting
1374 to the channel until we have sent the key. */
1375 tmp_len = strlen(channel->channel_key->cipher->name);
1377 silc_channel_key_payload_encode(idp->len, idp->data,
1378 strlen(channel->channel_key->
1380 channel->channel_key->cipher->name,
1381 channel->key_len / 8, channel->key);
1383 silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
1384 packet->data, packet->len, FALSE);
1386 silc_buffer_free(packet);
1387 silc_buffer_free(idp);
1390 /* Finally, send notify message to all clients on the channel about
1391 new user on the channel. */
1392 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1393 if (!cmd->pending) {
1394 /* Send JOIN notify to clients */
1395 SilcBuffer clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1396 silc_server_send_notify_to_channel(server, channel, FALSE,
1397 SILC_NOTIFY_TYPE_JOIN, 1,
1398 clidp->data, clidp->len);
1399 silc_buffer_free(clidp);
1401 /* Send NEW_CHANNEL_USER packet to primary route */
1402 if (!server->standalone)
1403 silc_server_send_new_channel_user(server, server->router->connection,
1404 server->server_type == SILC_SERVER ?
1406 channel->id, SILC_ID_CHANNEL_LEN,
1407 client->id, SILC_ID_CLIENT_LEN);
1409 /* This is pending command request. Send the notify after we have
1410 received the key for the channel from the router. */
1411 JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
1412 ctx->channel_name = channel->channel_name;
1413 ctx->nickname = client->nickname;
1414 ctx->username = client->username;
1415 ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
1416 ctx->channel = channel;
1417 ctx->server = server;
1418 ctx->client = client;
1419 silc_task_register(server->timeout_queue, sock->sock,
1420 silc_server_command_join_notify, ctx,
1421 0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1425 /* Send NAMES command reply to the joined channel so the user sees who
1426 is currently on the channel. */
1427 silc_server_command_send_names(server, sock, channel);
1432 silc_free(passphrase);
1435 /* Server side of command JOIN. Joins client into requested channel. If
1436 the channel does not exist it will be created. */
1438 SILC_SERVER_CMD_FUNC(join)
1440 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1441 SilcServer server = cmd->server;
1443 char *tmp, *channel_name = NULL, *cipher = NULL;
1444 SilcChannelEntry channel;
1445 unsigned int umode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
1447 SILC_LOG_DEBUG(("Start"));
1449 /* Check number of parameters */
1450 argc = silc_argument_get_arg_num(cmd->args);
1452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1453 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1458 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1462 /* Get channel name */
1463 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1466 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1471 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1472 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1473 SILC_STATUS_ERR_BAD_CHANNEL);
1474 silc_free(channel_name);
1478 /* Get cipher name */
1479 cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1481 /* See if the channel exists */
1482 channel = silc_idlist_find_channel_by_name(server->local_list, channel_name);
1484 /* Channel not found */
1486 /* If we are standalone server we don't have a router, we just create
1487 the channel by ourselves. */
1488 if (server->standalone) {
1489 channel = silc_server_create_new_channel(server, server->id, cipher,
1493 /* The channel does not exist on our server. We send JOIN command to
1494 our router which will handle the joining procedure (either creates
1495 the channel if it doesn't exist or joins the client to it) - if we
1496 are normal server. */
1497 if (server->server_type == SILC_SERVER) {
1498 SilcBuffer buffer = cmd->packet->buffer;
1500 /* Forward the original JOIN command to the router */
1501 silc_buffer_push(buffer, buffer->data - buffer->head);
1502 silc_server_packet_forward(server, (SilcSocketConnection)
1503 server->router->connection,
1504 buffer->data, buffer->len, TRUE);
1506 /* Add the command to be pending. It will be re-executed after
1507 router has replied back to us. */
1508 cmd->pending = TRUE;
1509 silc_server_command_pending(server, SILC_COMMAND_JOIN, 0,
1510 silc_server_command_join, context);
1514 /* We are router and the channel does not seem exist so we will check
1515 our global list as well for the channel. */
1516 channel = silc_idlist_find_channel_by_name(server->global_list,
1519 /* Channel really does not exist, create it */
1520 channel = silc_server_create_new_channel(server, server->id, cipher,
1522 umode |= SILC_CHANNEL_UMODE_CHANOP;
1523 umode |= SILC_CHANNEL_UMODE_CHANFO;
1528 /* Join to the channel */
1529 silc_server_command_join_channel(server, cmd, channel, umode);
1532 silc_server_command_free(cmd);
1535 /* Server side of command MOTD. Sends server's current "message of the
1536 day" to the client. */
1538 SILC_SERVER_CMD_FUNC(motd)
1540 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1541 SilcServer server = cmd->server;
1546 SILC_LOG_DEBUG(("Start"));
1548 argc = silc_argument_get_arg_num(cmd->args);
1550 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1551 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1555 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1556 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1560 /* XXX show currently only our motd */
1562 if (server->config && server->config->motd &&
1563 server->config->motd->motd_file) {
1566 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
1571 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
1577 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
1582 silc_server_command_free(cmd);
1585 SILC_SERVER_CMD_FUNC(umode)
1589 /* Checks that client has rights to add or remove channel modes. If any
1590 of the checks fails FALSE is returned. */
1592 int silc_server_check_cmode_rights(SilcChannelEntry channel,
1593 SilcChannelClientEntry client,
1596 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1597 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1599 /* Check whether has rights to change anything */
1600 if (!is_op && !is_fo)
1603 /* Check whether has rights to change everything */
1607 /* We know that client is channel operator, check that they are not
1608 changing anything that requires channel founder rights. Rest of the
1609 modes are available automatically for channel operator. */
1611 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1612 if (is_op && !is_fo)
1615 if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
1616 if (is_op && !is_fo)
1621 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1622 if (is_op && !is_fo)
1625 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1626 if (is_op && !is_fo)
1631 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1632 if (is_op && !is_fo)
1635 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1636 if (is_op && !is_fo)
1644 /* Server side command of CMODE. Changes channel mode */
1646 SILC_SERVER_CMD_FUNC(cmode)
1648 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1649 SilcServer server = cmd->server;
1650 SilcSocketConnection sock = cmd->sock;
1651 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1652 SilcChannelID *channel_id;
1653 SilcClientID *client_id;
1654 SilcChannelEntry channel;
1655 SilcChannelClientEntry chl;
1656 SilcBuffer packet, cidp;
1657 unsigned char *tmp, *tmp_id, *tmp_mask;
1658 unsigned int argc, mode_mask, tmp_len, tmp_len2;
1661 SILC_LOG_DEBUG(("Start"));
1663 argc = silc_argument_get_arg_num(cmd->args);
1665 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1666 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1671 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1675 /* Get Channel ID */
1676 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
1678 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1679 SILC_STATUS_ERR_NO_CHANNEL_ID);
1682 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
1684 /* Get the channel mode mask */
1685 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1688 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1691 SILC_GET32_MSB(mode_mask, tmp_mask);
1693 /* Get channel entry */
1694 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1696 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1697 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1701 /* Check whether this client is on the channel */
1702 if (!silc_server_client_on_channel(client, channel)) {
1703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1704 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1708 /* Get entry to the channel user list */
1709 silc_list_start(channel->user_list);
1710 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1711 if (chl->client == client)
1714 /* Check that client has rights to change any requested channel modes */
1715 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
1716 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1717 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1722 * Check the modes. Modes that requires nothing special operation are
1726 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
1727 /* Channel uses private keys to protect traffic. Client(s) has set the
1728 key locally they want to use, server does not know that key. */
1729 /* Nothing interesting to do here now */
1731 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1732 /* The mode is removed and we need to generate and distribute
1733 new channel key. Clients are not using private channel keys
1734 anymore after this. */
1735 unsigned int key_len;
1736 unsigned char channel_key[32];
1738 /* XXX Duplicated code, make own function for this!! LEAVE uses this
1741 /* Re-generate channel key */
1742 key_len = channel->key_len / 8;
1743 for (i = 0; i < key_len; i++)
1744 channel_key[i] = silc_rng_get_byte(server->rng);
1745 channel->channel_key->cipher->set_key(channel->channel_key->context,
1746 channel_key, key_len);
1747 memset(channel->key, 0, key_len);
1748 silc_free(channel->key);
1749 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1750 memcpy(channel->key, channel_key, key_len);
1751 memset(channel_key, 0, sizeof(channel_key));
1753 /* Encode channel key payload to be distributed on the channel */
1755 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1756 strlen(channel->channel_key->
1758 channel->channel_key->cipher->name,
1759 key_len, channel->key);
1761 /* If we are normal server then we will send it to our router. If we
1762 are router we will send it to all local servers that has clients on
1764 if (server->server_type == SILC_SERVER) {
1765 if (!server->standalone)
1766 silc_server_packet_send(server,
1767 cmd->server->router->connection,
1768 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1774 /* Send to locally connected clients on the channel */
1775 silc_server_packet_send_local_channel(server, channel,
1776 SILC_PACKET_CHANNEL_KEY, 0,
1777 packet->data, packet->len, FALSE);
1778 silc_buffer_free(packet);
1782 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
1783 /* User limit is set on channel */
1784 unsigned int user_limit;
1786 /* Get user limit */
1787 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1789 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
1790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1791 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1795 SILC_GET32_MSB(user_limit, tmp);
1796 channel->mode_data.user_limit = user_limit;
1799 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
1800 /* User limit mode is unset. Remove user limit */
1801 channel->mode_data.user_limit = 0;
1804 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
1805 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1806 /* Passphrase has been set to channel */
1808 /* Get the passphrase */
1809 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1812 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1816 /* Save the passphrase */
1817 channel->mode_data.passphrase = strdup(tmp);
1820 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1821 /* Passphrase mode is unset. remove the passphrase */
1822 if (channel->mode_data.passphrase) {
1823 silc_free(channel->mode_data.passphrase);
1824 channel->mode_data.passphrase = NULL;
1829 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
1830 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
1831 /* Ban list is specified for channel */
1834 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1837 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1841 /* XXX check that channel founder is not banned */
1843 /* Save the ban list */
1844 channel->mode_data.ban_list = strdup(tmp);
1847 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1848 /* Ban mode is unset. Remove the entire ban list */
1849 if (channel->mode_data.ban_list) {
1850 silc_free(channel->mode_data.ban_list);
1851 channel->mode_data.ban_list = NULL;
1856 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
1857 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
1858 /* Invite list is specified for channel */
1860 /* Get invite list */
1861 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1863 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1864 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1868 /* Save the invite linst */
1869 channel->mode_data.invite_list = strdup(tmp);
1872 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1873 /* Invite list mode is unset. Remove the entire invite list */
1874 if (channel->mode_data.invite_list) {
1875 silc_free(channel->mode_data.invite_list);
1876 channel->mode_data.invite_list = NULL;
1881 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
1882 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1883 /* Cipher to use protect the traffic */
1884 unsigned int key_len = 128;
1885 unsigned char channel_key[32];
1889 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
1891 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1892 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1896 cp = strchr(tmp, ':');
1902 /* XXX Duplicated code, make own function for this!! */
1904 /* Delete old cipher and allocate the new one */
1905 silc_cipher_free(channel->channel_key);
1906 silc_cipher_alloc(tmp, &channel->channel_key);
1908 /* Re-generate channel key */
1910 if (key_len > sizeof(channel_key))
1911 key_len = sizeof(channel_key);
1913 for (i = 0; i < key_len; i++)
1914 channel_key[i] = silc_rng_get_byte(server->rng);
1915 channel->channel_key->cipher->set_key(channel->channel_key->context,
1916 channel_key, key_len);
1917 memset(channel->key, 0, key_len);
1918 silc_free(channel->key);
1919 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1920 memcpy(channel->key, channel_key, key_len);
1921 memset(channel_key, 0, sizeof(channel_key));
1923 /* Encode channel key payload to be distributed on the channel */
1925 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1926 strlen(channel->channel_key->
1928 channel->channel_key->cipher->name,
1929 key_len, channel->key);
1931 /* If we are normal server then we will send it to our router. If we
1932 are router we will send it to all local servers that has clients on
1934 if (server->server_type == SILC_SERVER) {
1935 if (!server->standalone)
1936 silc_server_packet_send(server,
1937 cmd->server->router->connection,
1938 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1944 /* Send to locally connected clients on the channel */
1945 silc_server_packet_send_local_channel(server, channel,
1946 SILC_PACKET_CHANNEL_KEY, 0,
1947 packet->data, packet->len, FALSE);
1948 silc_buffer_free(packet);
1951 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1952 /* Cipher mode is unset. Remove the cipher and revert back to
1954 unsigned int key_len;
1955 unsigned char channel_key[32];
1957 if (channel->mode_data.cipher) {
1958 silc_free(channel->mode_data.cipher);
1959 channel->mode_data.cipher = NULL;
1960 channel->mode_data.key_len = 0;
1963 /* Generate new cipher and key for the channel */
1965 /* XXX Duplicated code, make own function for this!! */
1967 /* Delete old cipher and allocate default one */
1968 silc_cipher_free(channel->channel_key);
1969 if (!channel->cipher)
1970 silc_cipher_alloc("twofish", &channel->channel_key);
1972 silc_cipher_alloc(channel->cipher, &channel->channel_key);
1974 /* Re-generate channel key */
1975 key_len = channel->key_len / 8;
1976 for (i = 0; i < key_len; i++)
1977 channel_key[i] = silc_rng_get_byte(server->rng);
1978 channel->channel_key->cipher->set_key(channel->channel_key->context,
1979 channel_key, key_len);
1980 memset(channel->key, 0, key_len);
1981 silc_free(channel->key);
1982 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1983 memcpy(channel->key, channel_key, key_len);
1984 memset(channel_key, 0, sizeof(channel_key));
1986 /* Encode channel key payload to be distributed on the channel */
1988 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1989 strlen(channel->channel_key->
1991 channel->channel_key->cipher->name,
1992 key_len, channel->key);
1994 /* If we are normal server then we will send it to our router. If we
1995 are router we will send it to all local servers that has clients on
1997 if (server->server_type == SILC_SERVER) {
1998 if (!server->standalone)
1999 silc_server_packet_send(server,
2000 cmd->server->router->connection,
2001 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2007 /* Send to locally connected clients on the channel */
2008 silc_server_packet_send_local_channel(server, channel,
2009 SILC_PACKET_CHANNEL_KEY, 0,
2010 packet->data, packet->len, FALSE);
2011 silc_buffer_free(packet);
2015 /* Finally, set the mode */
2016 channel->mode = mode_mask;
2018 /* Send CMODE_CHANGE notify */
2019 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2020 silc_server_send_notify_to_channel(server, channel, TRUE,
2021 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2022 cidp->data, cidp->len,
2026 /* Send command reply to sender */
2027 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2028 SILC_STATUS_OK, 0, 1,
2030 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2031 packet->data, packet->len, FALSE);
2033 silc_buffer_free(packet);
2034 silc_free(channel_id);
2037 silc_server_command_free(cmd);
2040 /* Server side of CUMODE command. Changes client's mode on a channel. */
2042 SILC_SERVER_CMD_FUNC(cumode)
2044 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2045 SilcServer server = cmd->server;
2046 SilcSocketConnection sock = cmd->sock;
2047 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2048 SilcChannelID *channel_id;
2049 SilcClientID *client_id;
2050 SilcChannelEntry channel;
2051 SilcClientEntry target_client;
2052 SilcChannelClientEntry chl;
2053 SilcBuffer packet, idp;
2054 unsigned char *tmp, *tmp_id, *tmp_mask;
2055 unsigned int argc, target_mask, sender_mask, tmp_len;
2056 int i, notify = FALSE;
2058 SILC_LOG_DEBUG(("Start"));
2060 argc = silc_argument_get_arg_num(cmd->args);
2062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2063 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2068 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2072 /* Get Channel ID */
2073 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2075 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2076 SILC_STATUS_ERR_NO_CHANNEL_ID);
2079 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2081 /* Get channel entry */
2082 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
2084 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2085 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2089 /* Check whether sender is on the channel */
2090 if (!silc_server_client_on_channel(client, channel)) {
2091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2092 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2096 /* Check that client has rights to change other's rights */
2097 silc_list_start(channel->user_list);
2098 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2099 if (chl->client == client) {
2100 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2101 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2102 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2103 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2107 sender_mask = chl->mode;
2112 /* Get the target client's channel mode mask */
2113 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2116 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2119 SILC_GET32_MSB(target_mask, tmp_mask);
2121 /* Get target Client ID */
2122 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2124 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2125 SILC_STATUS_ERR_NO_CHANNEL_ID);
2128 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2130 /* Get target client's entry */
2131 target_client = silc_idlist_find_client_by_id(server->local_list, client_id);
2132 if (!target_client) {
2133 /* XXX If target client is not one of mine send to primary route */
2136 /* Check whether target client is on the channel */
2137 if (!silc_server_client_on_channel(target_client, channel)) {
2138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2139 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2143 /* Get entry to the channel user list */
2144 silc_list_start(channel->user_list);
2145 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2146 if (chl->client == target_client)
2153 /* If the target client is founder, no one else can change their mode
2155 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2156 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2157 SILC_STATUS_ERR_NOT_YOU);
2161 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2162 /* Cannot promote anyone to channel founder */
2163 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2164 SILC_STATUS_ERR_NOT_YOU);
2167 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2168 if (target_client == client) {
2169 /* Remove channel founder rights from itself */
2170 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2173 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2174 SILC_STATUS_ERR_NOT_YOU);
2180 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2181 /* Promote to operator */
2182 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2183 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2187 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2188 /* Demote to normal user */
2189 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2194 /* Send notify to channel, notify only if mode was actually changed. */
2196 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2197 silc_server_send_notify_to_channel(server, channel, TRUE,
2198 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2199 idp->data, idp->len,
2200 tmp_mask, 4, tmp_id, tmp_len);
2201 silc_buffer_free(idp);
2204 /* Send command reply to sender */
2205 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2206 SILC_STATUS_OK, 0, 2,
2208 3, tmp_id, tmp_len);
2209 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2210 packet->data, packet->len, FALSE);
2212 silc_buffer_free(packet);
2213 silc_free(channel_id);
2214 silc_free(client_id);
2217 silc_server_command_free(cmd);
2220 /* Server side of KICK command. Kicks client out of channel. */
2222 SILC_SERVER_CMD_FUNC(kick)
2224 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2225 SilcServer server = cmd->server;
2226 SilcSocketConnection sock = cmd->sock;
2227 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2231 SILC_SERVER_CMD_FUNC(restart)
2235 SILC_SERVER_CMD_FUNC(close)
2239 SILC_SERVER_CMD_FUNC(die)
2243 SILC_SERVER_CMD_FUNC(silcoper)
2247 /* Server side command of LEAVE. Removes client from a channel. */
2249 SILC_SERVER_CMD_FUNC(leave)
2251 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2252 SilcServer server = cmd->server;
2253 SilcSocketConnection sock = cmd->sock;
2254 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2256 SilcChannelEntry channel;
2258 unsigned int i, argc, key_len, len;
2259 unsigned char *tmp, channel_key[32];
2261 SILC_LOG_DEBUG(("Start"));
2263 argc = silc_argument_get_arg_num(cmd->args);
2265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2266 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2271 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2275 /* Get Channel ID */
2276 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2279 SILC_STATUS_ERR_NO_CHANNEL_ID);
2282 id = silc_id_payload_parse_id(tmp, len);
2284 /* Get channel entry */
2285 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2288 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2292 /* Check whether this client is on the channel */
2293 if (!silc_server_client_on_channel(id_entry, channel)) {
2294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2295 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2299 /* Notify routers that they should remove this client from their list
2300 of clients on the channel. */
2301 if (!server->standalone)
2302 silc_server_send_remove_channel_user(server,
2303 server->router->connection,
2304 server->server_type == SILC_ROUTER ?
2305 TRUE : FALSE, id_entry->id, id);
2307 /* Remove client from channel */
2308 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2313 /* If the channel does not exist anymore we won't send anything */
2317 /* Re-generate channel key */
2318 key_len = channel->key_len / 8;
2319 for (i = 0; i < key_len; i++)
2320 channel_key[i] = silc_rng_get_byte(server->rng);
2321 channel->channel_key->cipher->set_key(channel->channel_key->context,
2322 channel_key, key_len);
2323 memset(channel->key, 0, key_len);
2324 silc_free(channel->key);
2325 channel->key = silc_calloc(key_len, sizeof(*channel->key));
2326 memcpy(channel->key, channel_key, key_len);
2327 memset(channel_key, 0, sizeof(channel_key));
2329 /* Encode channel key payload to be distributed on the channel */
2331 silc_channel_key_payload_encode(len, tmp,
2332 strlen(channel->channel_key->cipher->name),
2333 channel->channel_key->cipher->name,
2334 key_len, channel->key);
2336 /* If we are normal server then we will send it to our router. If we
2337 are router we will send it to all local servers that has clients on
2339 if (server->server_type == SILC_SERVER) {
2340 if (!server->standalone)
2341 silc_server_packet_send(server,
2342 cmd->server->router->connection,
2343 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2349 /* Send to locally connected clients on the channel */
2350 silc_server_packet_send_local_channel(server, channel,
2351 SILC_PACKET_CHANNEL_KEY, 0,
2352 packet->data, packet->len, FALSE);
2354 silc_buffer_free(packet);
2358 silc_server_command_free(cmd);
2361 /* Server side of command NAMES. Resolves clients and their names currently
2362 joined on the requested channel. The name list is sent back to the
2365 SILC_SERVER_CMD_FUNC(names)
2367 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2368 SilcServer server = cmd->server;
2369 SilcChannelEntry channel;
2370 SilcChannelClientEntry chl;
2373 unsigned int i, len, len2, tmp_len, argc;
2375 char *name_list = NULL, *n;
2376 SilcBuffer client_id_list;
2377 SilcBuffer client_mode_list;
2379 SILC_LOG_DEBUG(("Start"));
2381 argc = silc_argument_get_arg_num(cmd->args);
2383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2384 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2389 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2393 /* Get Channel ID */
2394 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2396 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2397 SILC_STATUS_ERR_NO_CHANNEL_ID);
2400 id = silc_id_payload_parse_id(tmp, tmp_len);
2402 /* Check whether the channel exists. If we are normal server and the
2403 channel does not exist we will send this same command to our router
2404 which will know if the channel exists. */
2405 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2407 if (server->server_type == SILC_SERVER && !server->standalone) {
2408 /* XXX Send names command */
2410 cmd->pending = TRUE;
2411 silc_server_command_pending(server, SILC_COMMAND_NAMES, 0,
2412 silc_server_command_names, context);
2416 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2417 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2421 /* Assemble the name list now */
2424 silc_list_start(channel->user_list);
2426 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2427 n = chl->client->nickname;
2431 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2432 memcpy(name_list + (len - len2), n, len2);
2435 if (i == silc_list_count(channel->user_list) - 1)
2437 memcpy(name_list + len, ",", 1);
2445 /* Assemble the Client ID list now */
2446 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2447 silc_list_count(channel->user_list));
2448 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2449 silc_list_start(channel->user_list);
2450 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2453 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2454 silc_buffer_format(client_id_list,
2455 SILC_STR_UI_XNSTRING(idp->data, idp->len),
2457 silc_buffer_pull(client_id_list, idp->len);
2458 silc_buffer_free(idp);
2460 silc_buffer_push(client_id_list,
2461 client_id_list->data - client_id_list->head);
2463 /* Assemble mode list */
2464 client_mode_list = silc_buffer_alloc(4 *
2465 silc_list_count(channel->user_list));
2466 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2467 silc_list_start(channel->user_list);
2468 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2469 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2470 silc_buffer_pull(client_mode_list, 4);
2472 silc_buffer_push(client_mode_list,
2473 client_mode_list->data - client_mode_list->head);
2476 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2477 SILC_STATUS_OK, 0, 4,
2481 4, client_id_list->data,
2482 client_id_list->len,
2483 5, client_mode_list->data,
2484 client_mode_list->len);
2485 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2486 packet->data, packet->len, FALSE);
2488 silc_buffer_free(packet);
2489 silc_free(name_list);
2490 silc_buffer_free(client_id_list);
2491 silc_buffer_free(client_mode_list);
2495 silc_server_command_free(cmd);