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 that is called after router has replied to server's
1224 JOIN command it forwarded to the router. The route has joined and possibly
1225 creaetd the channel. This function adds the client to the channel's user
1228 SILC_SERVER_CMD_FUNC(add_to_channel)
1230 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1231 SilcServer server = cmd->server;
1232 SilcClientEntry client;
1233 SilcChannelEntry channel;
1234 SilcChannelClientEntry chl;
1237 /* Get channel name */
1238 channel_name = silc_argument_get_arg_type(cmd->args, 1, NULL);
1240 /* Get client entry */
1241 client = (SilcClientEntry)cmd->sock->user_data;
1243 /* Get channel entry */
1244 channel = silc_idlist_find_channel_by_name(server->local_list, channel_name);
1246 /* Join the client to the channel by adding it to channel's user list.
1247 Add also the channel to client entry's channels list for fast cross-
1249 chl = silc_calloc(1, sizeof(*chl));
1250 //chl->mode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
1251 chl->client = client;
1252 chl->channel = channel;
1253 silc_list_add(channel->user_list, chl);
1254 silc_list_add(client->channels, chl);
1257 silc_server_command_free(cmd);
1260 /* Internal routine to join channel. The channel sent to this function
1261 has been either created or resolved from ID lists. This joins the sent
1262 client to the channel. */
1264 static void silc_server_command_join_channel(SilcServer server,
1265 SilcServerCommandContext cmd,
1266 SilcChannelEntry channel,
1270 SilcSocketConnection sock = cmd->sock;
1272 unsigned int tmp_len;
1273 unsigned char *passphrase = NULL, mode[4];
1274 SilcClientEntry client;
1275 SilcChannelClientEntry chl;
1276 SilcBuffer reply, chidp, clidp;
1281 /* Get passphrase */
1282 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1284 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1285 memcpy(passphrase, tmp, tmp_len);
1289 * Check channel modes
1292 /* Check invite list if channel is invite-only channel */
1293 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1294 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1295 /* Invite list is specified. Check whether client is invited in the
1296 list. If not, then check whether it has been invited otherwise. */
1299 /* XXX client must be invited to be able to join the channel */
1303 /* Check ban list if set */
1304 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1308 /* Check the channel passphrase if set. */
1309 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1310 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1311 strlen(channel->mode_data.passphrase))) {
1312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1313 SILC_STATUS_ERR_BAD_PASSWORD);
1318 /* Check user count limit if set. */
1319 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1320 if (silc_list_count(channel->user_list) + 1 >
1321 channel->mode_data.user_limit) {
1322 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1323 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1329 * Client is allowed to join to the channel. Make it happen.
1332 /* If the JOIN request was forwarded to us we will make a bit slower
1333 query to get the client pointer. Otherwise, we get the client pointer
1335 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1336 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1337 client = silc_idlist_find_client_by_id(server->local_list, id);
1340 SILC_LOG_ERROR(("Forwarded join command did not find the client who "
1341 "wanted to join the channel"));
1346 client = (SilcClientEntry)sock->user_data;
1349 /* Check whether the client already is on the channel */
1350 if (silc_server_client_on_channel(client, channel)) {
1351 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1352 SILC_STATUS_ERR_USER_ON_CHANNEL);
1356 /* Generate new channel key as protocol dictates */
1358 silc_server_create_channel_key(server, channel, 0);
1360 /* Join the client to the channel by adding it to channel's user list.
1361 Add also the channel to client entry's channels list for fast cross-
1363 chl = silc_calloc(1, sizeof(*chl));
1365 chl->client = client;
1366 chl->channel = channel;
1367 silc_list_add(channel->user_list, chl);
1368 silc_list_add(client->channels, chl);
1370 /* Encode Client ID Payload of the original client who wants to join */
1371 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1373 /* Encode command reply packet */
1374 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1375 SILC_PUT32_MSB(channel->mode, mode);
1376 if (!channel->topic) {
1378 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1379 SILC_STATUS_OK, 0, 3,
1380 2, channel->channel_name,
1381 strlen(channel->channel_name),
1382 3, chidp->data, chidp->len,
1386 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1387 SILC_STATUS_OK, 0, 4,
1388 2, channel->channel_name,
1389 strlen(channel->channel_name),
1390 3, chidp->data, chidp->len,
1393 strlen(channel->topic));
1396 if (server->server_type == SILC_ROUTER &&
1397 cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1398 /* We are router and server has forwarded this command to us. Send
1399 all replys to the server. */
1402 /* Send command reply destined to the original client */
1403 tmpid = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1404 silc_server_packet_send_dest(cmd->server, sock,
1405 SILC_PACKET_COMMAND_REPLY, 0,
1406 tmpid, cmd->packet->src_id_type,
1407 reply->data, reply->len, FALSE);
1409 /* Distribute new channel key to local cell and local clients. */
1410 silc_server_send_channel_key(server, channel, FALSE);
1412 /* Distribute JOIN notify into the cell for everbody on the channel */
1413 silc_server_send_notify_to_channel(server, channel, FALSE,
1414 SILC_NOTIFY_TYPE_JOIN, 1,
1415 clidp->data, clidp->len);
1417 /* Broadcast NEW_CHANNEL_USER packet to primary route */
1418 silc_server_send_new_channel_user(server, server->router->connection,
1419 TRUE, channel->id, SILC_ID_CHANNEL_LEN,
1420 client->id, SILC_ID_CLIENT_LEN);
1424 /* Client sent the command. Send all replies directly to the client. */
1426 /* Send command reply */
1427 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1428 reply->data, reply->len, FALSE);
1430 /* Send the channel key. Channel key is sent before any other packet
1432 silc_server_send_channel_key(server, channel, server->standalone ?
1435 /* Send JOIN notify to locally connected clients on the channel */
1436 silc_server_send_notify_to_channel(server, channel, FALSE,
1437 SILC_NOTIFY_TYPE_JOIN, 1,
1438 clidp->data, clidp->len);
1440 /* Send NEW_CHANNEL_USER packet to our primary router */
1441 if (!server->standalone)
1442 silc_server_send_new_channel_user(server, server->router->connection,
1444 channel->id, SILC_ID_CHANNEL_LEN,
1445 client->id, SILC_ID_CLIENT_LEN);
1447 /* Send NAMES command reply to the joined channel so the user sees who
1448 is currently on the channel. */
1449 silc_server_command_send_names(server, sock, channel);
1452 silc_buffer_free(reply);
1453 silc_buffer_free(clidp);
1454 silc_buffer_free(chidp);
1458 silc_free(passphrase);
1461 /* Server side of command JOIN. Joins client into requested channel. If
1462 the channel does not exist it will be created. */
1464 SILC_SERVER_CMD_FUNC(join)
1466 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1467 SilcServer server = cmd->server;
1469 char *tmp, *channel_name = NULL, *cipher = NULL;
1470 SilcChannelEntry channel;
1471 unsigned int umode = 0;
1472 int created = FALSE;
1474 SILC_LOG_DEBUG(("Start"));
1476 /* Check number of parameters */
1477 argc = silc_argument_get_arg_num(cmd->args);
1479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1480 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1484 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1485 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1489 /* Get channel name */
1490 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1492 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1493 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1498 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1500 SILC_STATUS_ERR_BAD_CHANNEL);
1501 silc_free(channel_name);
1505 /* Get cipher name */
1506 cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1508 /* See if the channel exists */
1509 channel = silc_idlist_find_channel_by_name(server->local_list, channel_name);
1511 /* Channel not found */
1513 /* If we are standalone server we don't have a router, we just create
1514 the channel by ourselves. */
1515 if (server->standalone) {
1516 channel = silc_server_create_new_channel(server, server->id, cipher,
1518 umode |= SILC_CHANNEL_UMODE_CHANOP;
1519 umode |= SILC_CHANNEL_UMODE_CHANFO;
1523 /* The channel does not exist on our server. If we are normal server
1524 we will send JOIN command to our router which will handle the joining
1525 procedure (either creates the channel if it doesn't exist or joins
1526 the client to it). */
1527 if (server->server_type == SILC_SERVER) {
1528 /* Forward the original JOIN command to the router */
1529 silc_buffer_push(cmd->packet->buffer,
1530 cmd->packet->buffer->data -
1531 cmd->packet->buffer->head);
1532 silc_server_packet_forward(server, (SilcSocketConnection)
1533 server->router->connection,
1534 cmd->packet->buffer->data,
1535 cmd->packet->buffer->len, TRUE);
1537 /* Register handler that will be called after the router has replied
1538 to us. We will add the client to the new channel in this callback
1539 function. Will be called from JOIN command reply. */
1540 silc_server_command_pending(server, SILC_COMMAND_JOIN,
1541 ++server->router->data.cmd_ident,
1542 silc_server_command_add_to_channel,
1547 /* We are router and the channel does not seem exist so we will check
1548 our global list as well for the channel. */
1549 channel = silc_idlist_find_channel_by_name(server->global_list,
1552 /* Channel really does not exist, create it */
1553 channel = silc_server_create_new_channel(server, server->id, cipher,
1555 umode |= SILC_CHANNEL_UMODE_CHANOP;
1556 umode |= SILC_CHANNEL_UMODE_CHANFO;
1562 /* Join to the channel */
1563 silc_server_command_join_channel(server, cmd, channel, created, umode);
1566 silc_server_command_free(cmd);
1569 /* Server side of command MOTD. Sends server's current "message of the
1570 day" to the client. */
1572 SILC_SERVER_CMD_FUNC(motd)
1574 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1575 SilcServer server = cmd->server;
1580 SILC_LOG_DEBUG(("Start"));
1582 argc = silc_argument_get_arg_num(cmd->args);
1584 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1585 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1589 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1590 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1594 /* XXX show currently only our motd */
1596 if (server->config && server->config->motd &&
1597 server->config->motd->motd_file) {
1600 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
1605 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
1611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
1616 silc_server_command_free(cmd);
1619 SILC_SERVER_CMD_FUNC(umode)
1623 /* Checks that client has rights to add or remove channel modes. If any
1624 of the checks fails FALSE is returned. */
1626 int silc_server_check_cmode_rights(SilcChannelEntry channel,
1627 SilcChannelClientEntry client,
1630 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1631 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1633 /* Check whether has rights to change anything */
1634 if (!is_op && !is_fo)
1637 /* Check whether has rights to change everything */
1641 /* We know that client is channel operator, check that they are not
1642 changing anything that requires channel founder rights. Rest of the
1643 modes are available automatically for channel operator. */
1645 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1646 if (is_op && !is_fo)
1649 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1650 if (is_op && !is_fo)
1655 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1656 if (is_op && !is_fo)
1659 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1660 if (is_op && !is_fo)
1665 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1666 if (is_op && !is_fo)
1669 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1670 if (is_op && !is_fo)
1678 /* Server side command of CMODE. Changes channel mode */
1680 SILC_SERVER_CMD_FUNC(cmode)
1682 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1683 SilcServer server = cmd->server;
1684 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1685 SilcChannelID *channel_id;
1686 SilcChannelEntry channel;
1687 SilcChannelClientEntry chl;
1688 SilcBuffer packet, cidp;
1689 unsigned char *tmp, *tmp_id, *tmp_mask;
1690 unsigned int argc, mode_mask, tmp_len, tmp_len2;
1692 SILC_LOG_DEBUG(("Start"));
1694 argc = silc_argument_get_arg_num(cmd->args);
1696 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1697 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1701 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1702 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1706 /* Get Channel ID */
1707 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
1709 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1710 SILC_STATUS_ERR_NO_CHANNEL_ID);
1713 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
1715 /* Get the channel mode mask */
1716 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1719 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1722 SILC_GET32_MSB(mode_mask, tmp_mask);
1724 /* Get channel entry */
1725 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1728 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1732 /* Check whether this client is on the channel */
1733 if (!silc_server_client_on_channel(client, channel)) {
1734 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1735 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1739 /* Get entry to the channel user list */
1740 silc_list_start(channel->user_list);
1741 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1742 if (chl->client == client)
1745 /* Check that client has rights to change any requested channel modes */
1746 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
1747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1748 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1753 * Check the modes. Modes that requires nothing special operation are
1757 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
1758 /* Channel uses private keys to protect traffic. Client(s) has set the
1759 key locally they want to use, server does not know that key. */
1760 /* Nothing interesting to do here now */
1762 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1763 /* The mode is removed and we need to generate and distribute
1764 new channel key. Clients are not using private channel keys
1765 anymore after this. */
1767 /* XXX Duplicated code, make own function for this!! LEAVE uses this
1770 /* Re-generate channel key */
1771 silc_server_create_channel_key(server, channel, 0);
1773 /* Encode channel key payload to be distributed on the channel */
1775 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1776 strlen(channel->channel_key->
1778 channel->channel_key->cipher->name,
1779 channel->key_len / 8, channel->key);
1781 /* If we are normal server then we will send it to our router. If we
1782 are router we will send it to all local servers that has clients on
1784 if (server->server_type == SILC_SERVER) {
1785 if (!server->standalone)
1786 silc_server_packet_send(server,
1787 cmd->server->router->connection,
1788 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1794 /* Send to locally connected clients on the channel */
1795 silc_server_packet_send_local_channel(server, channel,
1796 SILC_PACKET_CHANNEL_KEY, 0,
1797 packet->data, packet->len, FALSE);
1798 silc_buffer_free(packet);
1802 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
1803 /* User limit is set on channel */
1804 unsigned int user_limit;
1806 /* Get user limit */
1807 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1809 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
1810 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1811 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1815 SILC_GET32_MSB(user_limit, tmp);
1816 channel->mode_data.user_limit = user_limit;
1819 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
1820 /* User limit mode is unset. Remove user limit */
1821 channel->mode_data.user_limit = 0;
1824 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
1825 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1826 /* Passphrase has been set to channel */
1828 /* Get the passphrase */
1829 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1831 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1832 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1836 /* Save the passphrase */
1837 channel->mode_data.passphrase = strdup(tmp);
1840 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1841 /* Passphrase mode is unset. remove the passphrase */
1842 if (channel->mode_data.passphrase) {
1843 silc_free(channel->mode_data.passphrase);
1844 channel->mode_data.passphrase = NULL;
1849 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
1850 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
1851 /* Ban list is specified for channel */
1854 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1856 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1857 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1861 /* XXX check that channel founder is not banned */
1863 /* Save the ban list */
1864 channel->mode_data.ban_list = strdup(tmp);
1867 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1868 /* Ban mode is unset. Remove the entire ban list */
1869 if (channel->mode_data.ban_list) {
1870 silc_free(channel->mode_data.ban_list);
1871 channel->mode_data.ban_list = NULL;
1876 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
1877 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
1878 /* Invite list is specified for channel */
1880 /* Get invite list */
1881 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1883 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1884 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1888 /* Save the invite linst */
1889 channel->mode_data.invite_list = strdup(tmp);
1892 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1893 /* Invite list mode is unset. Remove the entire invite list */
1894 if (channel->mode_data.invite_list) {
1895 silc_free(channel->mode_data.invite_list);
1896 channel->mode_data.invite_list = NULL;
1901 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
1902 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1903 /* Cipher to use protect the traffic */
1904 unsigned int key_len = 128;
1908 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
1910 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1911 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1915 cp = strchr(tmp, ':');
1921 /* XXX Duplicated code, make own function for this!! */
1923 /* Delete old cipher and allocate the new one */
1924 silc_cipher_free(channel->channel_key);
1925 silc_cipher_alloc(tmp, &channel->channel_key);
1931 /* Re-generate channel key */
1932 silc_server_create_channel_key(server, channel, key_len);
1934 /* Encode channel key payload to be distributed on the channel */
1936 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1937 strlen(channel->channel_key->
1939 channel->channel_key->cipher->name,
1940 channel->key_len / 8, channel->key);
1942 /* If we are normal server then we will send it to our router. If we
1943 are router we will send it to all local servers that has clients on
1945 if (server->server_type == SILC_SERVER) {
1946 if (!server->standalone)
1947 silc_server_packet_send(server,
1948 cmd->server->router->connection,
1949 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1955 /* Send to locally connected clients on the channel */
1956 silc_server_packet_send_local_channel(server, channel,
1957 SILC_PACKET_CHANNEL_KEY, 0,
1958 packet->data, packet->len, FALSE);
1959 silc_buffer_free(packet);
1962 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1963 /* Cipher mode is unset. Remove the cipher and revert back to
1966 if (channel->mode_data.cipher) {
1967 silc_free(channel->mode_data.cipher);
1968 channel->mode_data.cipher = NULL;
1969 channel->mode_data.key_len = 0;
1972 /* Generate new cipher and key for the channel */
1974 /* XXX Duplicated code, make own function for this!! */
1976 /* Delete old cipher and allocate default one */
1977 silc_cipher_free(channel->channel_key);
1978 if (!channel->cipher)
1979 silc_cipher_alloc("twofish", &channel->channel_key);
1981 silc_cipher_alloc(channel->cipher, &channel->channel_key);
1983 /* Re-generate channel key */
1984 silc_server_create_channel_key(server, channel, 0);
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 channel->key_len / 8, 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 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2047 SilcChannelID *channel_id;
2048 SilcClientID *client_id;
2049 SilcChannelEntry channel;
2050 SilcClientEntry target_client;
2051 SilcChannelClientEntry chl;
2052 SilcBuffer packet, idp;
2053 unsigned char *tmp_id, *tmp_mask;
2054 unsigned int argc, target_mask, sender_mask, tmp_len;
2057 SILC_LOG_DEBUG(("Start"));
2059 argc = silc_argument_get_arg_num(cmd->args);
2061 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2062 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2066 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2067 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2071 /* Get Channel ID */
2072 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2074 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2075 SILC_STATUS_ERR_NO_CHANNEL_ID);
2078 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2080 /* Get channel entry */
2081 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
2083 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2084 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2088 /* Check whether sender is on the channel */
2089 if (!silc_server_client_on_channel(client, channel)) {
2090 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2091 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2095 /* Check that client has rights to change other's rights */
2096 silc_list_start(channel->user_list);
2097 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2098 if (chl->client == client) {
2099 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2100 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2101 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2102 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2106 sender_mask = chl->mode;
2111 /* Get the target client's channel mode mask */
2112 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2114 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2115 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2118 SILC_GET32_MSB(target_mask, tmp_mask);
2120 /* Get target Client ID */
2121 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2123 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2124 SILC_STATUS_ERR_NO_CHANNEL_ID);
2127 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2129 /* Get target client's entry */
2130 target_client = silc_idlist_find_client_by_id(server->local_list, client_id);
2131 if (!target_client) {
2132 /* XXX If target client is not one of mine send to primary route */
2135 /* Check whether target client is on the channel */
2136 if (!silc_server_client_on_channel(target_client, channel)) {
2137 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2138 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2142 /* Get entry to the channel user list */
2143 silc_list_start(channel->user_list);
2144 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2145 if (chl->client == target_client)
2152 /* If the target client is founder, no one else can change their mode
2154 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2155 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2156 SILC_STATUS_ERR_NOT_YOU);
2160 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2161 /* Cannot promote anyone to channel founder */
2162 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2163 SILC_STATUS_ERR_NOT_YOU);
2166 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2167 if (target_client == client) {
2168 /* Remove channel founder rights from itself */
2169 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2172 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2173 SILC_STATUS_ERR_NOT_YOU);
2179 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2180 /* Promote to operator */
2181 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2182 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2186 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2187 /* Demote to normal user */
2188 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2193 /* Send notify to channel, notify only if mode was actually changed. */
2195 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2196 silc_server_send_notify_to_channel(server, channel, TRUE,
2197 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2198 idp->data, idp->len,
2199 tmp_mask, 4, tmp_id, tmp_len);
2200 silc_buffer_free(idp);
2203 /* Send command reply to sender */
2204 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2205 SILC_STATUS_OK, 0, 2,
2207 3, tmp_id, tmp_len);
2208 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2209 packet->data, packet->len, FALSE);
2211 silc_buffer_free(packet);
2212 silc_free(channel_id);
2213 silc_free(client_id);
2216 silc_server_command_free(cmd);
2219 /* Server side of KICK command. Kicks client out of channel. */
2221 SILC_SERVER_CMD_FUNC(kick)
2225 SILC_SERVER_CMD_FUNC(restart)
2229 SILC_SERVER_CMD_FUNC(close)
2233 SILC_SERVER_CMD_FUNC(die)
2237 SILC_SERVER_CMD_FUNC(silcoper)
2241 /* Server side command of LEAVE. Removes client from a channel. */
2243 SILC_SERVER_CMD_FUNC(leave)
2245 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2246 SilcServer server = cmd->server;
2247 SilcSocketConnection sock = cmd->sock;
2248 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2250 SilcChannelEntry channel;
2252 unsigned int i, argc, len;
2255 SILC_LOG_DEBUG(("Start"));
2257 argc = silc_argument_get_arg_num(cmd->args);
2259 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2260 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2264 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2265 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2269 /* Get Channel ID */
2270 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2273 SILC_STATUS_ERR_NO_CHANNEL_ID);
2276 id = silc_id_payload_parse_id(tmp, len);
2278 /* Get channel entry */
2279 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2282 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2286 /* Check whether this client is on the channel */
2287 if (!silc_server_client_on_channel(id_entry, channel)) {
2288 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2289 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2293 /* Notify routers that they should remove this client from their list
2294 of clients on the channel. */
2295 if (!server->standalone)
2296 silc_server_send_remove_channel_user(server,
2297 server->router->connection,
2298 server->server_type == SILC_ROUTER ?
2299 TRUE : FALSE, id_entry->id, id);
2301 /* Remove client from channel */
2302 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2307 /* If the channel does not exist anymore we won't send anything */
2311 /* Re-generate channel key */
2312 silc_server_create_channel_key(server, channel, 0);
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 channel->key_len / 8, 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);