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 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
83 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
85 SILC_LOG_DEBUG(("Start")); \
88 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS, \
89 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
90 silc_server_command_free(cmd); \
94 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS, \
95 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
96 silc_server_command_free(cmd); \
101 /* Returns TRUE if the connection is registered. Unregistered connections
102 usually cannot send commands hence the check. */
104 static int silc_server_is_registered(SilcServer server,
105 SilcSocketConnection sock,
106 SilcServerCommandContext cmd,
109 SilcIDListData idata = (SilcIDListData)sock->user_data;
110 if (idata->registered)
113 silc_server_command_send_status_reply(cmd, command,
114 SILC_STATUS_ERR_NOT_REGISTERED);
115 silc_server_command_free(cmd);
119 /* Processes received command packet. */
121 void silc_server_command_process(SilcServer server,
122 SilcSocketConnection sock,
123 SilcPacketContext *packet)
125 SilcServerCommandContext ctx;
126 SilcServerCommand *cmd;
129 /* XXX allow commands in but do not execute them more than once per
132 /* Check whether it is allowed for this connection to execute any
134 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
136 SilcClientEntry client = (SilcClientEntry)sock->user_data;
141 /* Allow only one command executed in 2 seconds. */
142 curtime = time(NULL);
143 if (client->last_command && (curtime - client->last_command) < 2)
146 /* Update access time */
147 client->last_command = curtime;
151 /* Allocate command context. This must be free'd by the
152 command routine receiving it. */
153 ctx = silc_calloc(1, sizeof(*ctx));
154 ctx->server = server;
156 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
158 /* Parse the command payload in the packet */
159 ctx->payload = silc_command_payload_parse(packet->buffer);
161 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
162 silc_buffer_free(packet->buffer);
163 silc_packet_context_free(packet);
167 ctx->args = silc_command_get_args(ctx->payload);
169 /* Execute command. If this fails the packet is dropped. */
170 for (cmd = silc_command_list; cmd->cb; cmd++)
171 if (cmd->cmd == silc_command_get(ctx->payload)) {
173 if (!(cmd->flags & SILC_CF_REG)) {
178 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
185 SILC_LOG_ERROR(("Unknown command, packet dropped"));
186 silc_server_command_free(ctx);
191 /* Add new pending command to be executed when reply to a command has been
192 received. The `reply_cmd' is the command that will call the `callback'
193 with `context' when reply has been received. If `ident' is non-zero
194 the `callback' will be executed when received reply with command
195 identifier `ident'. */
197 void silc_server_command_pending(SilcServer server,
198 SilcCommand reply_cmd,
199 unsigned short ident,
200 SilcCommandCb callback,
203 SilcServerCommandPending *reply;
205 reply = silc_calloc(1, sizeof(*reply));
206 reply->reply_cmd = reply_cmd;
207 reply->ident = ident;
208 reply->context = context;
209 reply->callback = callback;
210 silc_dlist_add(server->pending_commands, reply);
213 /* Deletes pending command by reply command type. */
215 void silc_server_command_pending_del(SilcServer server,
216 SilcCommand reply_cmd,
217 unsigned short ident)
219 SilcServerCommandPending *r;
221 silc_dlist_start(server->pending_commands);
222 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
223 if (r->reply_cmd == reply_cmd && r->ident == ident) {
224 silc_dlist_del(server->pending_commands, r);
230 /* Checks for pending commands and marks callbacks to be called from
231 the command reply function. Returns TRUE if there were pending command. */
233 int silc_server_command_pending_check(SilcServer server,
234 SilcServerCommandReplyContext ctx,
236 unsigned short ident)
238 SilcServerCommandPending *r;
240 silc_dlist_start(server->pending_commands);
241 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
242 if (r->reply_cmd == command && r->ident == ident) {
243 ctx->context = r->context;
244 ctx->callback = r->callback;
253 /* Free's the command context allocated before executing the command */
255 static void silc_server_command_free(SilcServerCommandContext cmd)
259 silc_command_free_payload(cmd->payload);
261 silc_packet_context_free(cmd->packet);
266 /* Sends simple status message as command reply packet */
269 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
271 SilcCommandStatus status)
275 SILC_LOG_DEBUG(("Sending command status %d", status));
277 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
278 silc_server_packet_send(cmd->server, cmd->sock,
279 SILC_PACKET_COMMAND_REPLY, 0,
280 buffer->data, buffer->len, FALSE);
281 silc_buffer_free(buffer);
284 /* Sends command status reply with one extra argument. The argument
285 type must be sent as argument. */
288 silc_server_command_send_status_data(SilcServerCommandContext cmd,
290 SilcCommandStatus status,
291 unsigned int arg_type,
293 unsigned int arg_len)
297 SILC_LOG_DEBUG(("Sending command status %d", status));
299 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
300 arg_type, arg, arg_len);
301 silc_server_packet_send(cmd->server, cmd->sock,
302 SILC_PACKET_COMMAND_REPLY, 0,
303 buffer->data, buffer->len, FALSE);
304 silc_buffer_free(buffer);
308 silc_server_command_whois_parse(SilcServerCommandContext cmd,
309 SilcClientID **client_id,
316 unsigned int argc = silc_argument_get_arg_num(cmd->args);
318 /* If client ID is in the command it must be used instead of nickname */
319 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
321 /* No ID, get the nickname@server string and parse it. */
322 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
324 if (strchr(tmp, '@')) {
325 len = strcspn(tmp, "@");
326 *nickname = silc_calloc(len + 1, sizeof(char));
327 memcpy(*nickname, tmp, len);
328 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
329 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
331 *nickname = strdup(tmp);
334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
335 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
339 /* Command includes ID, use that */
340 *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);
350 silc_free(*nickname);
352 silc_free(*server_name);
363 silc_server_command_whois_check(SilcServerCommandContext cmd,
364 SilcClientEntry *clients,
365 unsigned int clients_count)
367 SilcServer server = cmd->server;
369 SilcClientEntry entry;
371 for (i = 0; i < clients_count; i++) {
374 if (!entry->nickname || !entry->username || !entry->userinfo) {
377 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
378 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
380 /* Send WHOIS command to fastest route for the client ID */
381 silc_server_packet_send(server,
382 silc_server_route_get(server, entry->id,
384 SILC_PACKET_COMMAND, cmd->packet->flags,
385 tmpbuf->data, tmpbuf->len, TRUE);
387 /* Reprocess this packet after received reply */
388 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
389 silc_command_get_ident(cmd->payload),
390 silc_server_command_whois, (void *)cmd);
393 silc_buffer_free(tmpbuf);
402 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
403 SilcClientEntry *clients,
404 unsigned int clients_count)
406 SilcServer server = cmd->server;
408 int i, count = 0, len;
409 SilcBuffer packet, idp;
410 SilcClientEntry entry;
411 SilcCommandStatus status;
413 status = SILC_STATUS_OK;
414 if (clients_count > 1)
415 status = SILC_STATUS_LIST_START;
417 for (i = 0; i < clients_count; i++) {
420 if (count && i - 1 == count)
423 if (clients_count > 2)
424 status = SILC_STATUS_LIST_ITEM;
426 if (clients_count > 1 && i == clients_count - 1)
427 status = SILC_STATUS_LIST_END;
429 /* Send WHOIS reply */
430 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
431 tmp = silc_argument_get_first_arg(cmd->args, NULL);
434 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
435 char nh[256], uh[256];
436 unsigned char idle[4];
437 SilcSocketConnection hsock;
439 memset(uh, 0, sizeof(uh));
440 memset(nh, 0, sizeof(nh));
442 strncat(nh, entry->nickname, strlen(entry->nickname));
444 len = entry->router ? strlen(entry->router->server_name) :
445 strlen(server->server_name);
446 strncat(nh, entry->router ? entry->router->server_name :
447 server->server_name, len);
449 strncat(uh, entry->username, strlen(entry->username));
451 hsock = (SilcSocketConnection)entry->connection;
452 len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
453 strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
455 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
460 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
462 2, idp->data, idp->len,
466 strlen(entry->userinfo),
470 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
472 2, idp->data, idp->len,
480 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
482 2, idp->data, idp->len,
484 strlen(entry->nickname),
485 4, tmp, strlen(tmp)); /* XXX */
487 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
488 0, packet->data, packet->len, FALSE);
490 silc_buffer_free(packet);
491 silc_buffer_free(idp);
496 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
498 SilcServer server = cmd->server;
499 char *nick = NULL, *server_name = NULL;
500 int count = 0, clients_count;
501 SilcClientID *client_id = NULL;
502 SilcClientEntry *clients = NULL, entry;
505 /* Parse the whois request */
506 if (!silc_server_command_whois_parse(cmd, &client_id, &nick,
507 &server_name, &count))
510 /* Protocol dictates that we must always send the received WHOIS request
511 to our router if we are normal server, so let's do it now unless we
512 are standalone. We will not send any replies to the client until we
513 have received reply from the router. */
514 if (server->server_type == SILC_SERVER &&
515 !cmd->pending && !server->standalone) {
518 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
519 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
521 /* Send WHOIS command to our router */
522 silc_server_packet_send(server, (SilcSocketConnection)
523 server->router->connection,
524 SILC_PACKET_COMMAND, cmd->packet->flags,
525 tmpbuf->data, tmpbuf->len, TRUE);
527 /* Reprocess this packet after received reply from router */
528 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
529 silc_command_get_ident(cmd->payload),
530 silc_server_command_whois, (void *)cmd);
533 silc_buffer_free(tmpbuf);
538 /* We are ready to process the command request. Let's search for the
539 requested client and send reply to the requesting client. */
541 /* Get all clients matching that ID or nickname from local list */
543 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
545 clients = silc_calloc(1, sizeof(*clients));
550 clients = silc_idlist_get_clients_by_nickname(server->local_list,
555 /* If we are router we will check our global list as well. */
556 if (!clients && server->server_type == SILC_ROUTER) {
558 entry = silc_idlist_find_client_by_id(server->global_list, client_id);
560 clients = silc_calloc(1, sizeof(*clients));
565 clients = silc_idlist_get_clients_by_nickname(server->global_list,
572 /* Such a client really does not exist in the SILC network. */
573 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
574 SILC_STATUS_ERR_NO_SUCH_NICK,
575 3, nick, strlen(nick));
579 /* Router always finds the client entry if it exists in the SILC network.
580 However, it might be incomplete entry and does not include all the
581 mandatory fields that WHOIS command reply requires. Check for these and
582 make query from the server who owns the client if some fields are
584 if (server->server_type == SILC_ROUTER &&
585 !silc_server_command_whois_check(cmd, clients, clients_count)) {
590 /* Send the command reply to the client */
591 silc_server_command_whois_send_reply(cmd, clients, clients_count);
597 silc_free(client_id);
601 silc_free(server_name);
607 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
609 SilcServer server = cmd->server;
610 char *nick = NULL, *server_name = NULL;
611 int count = 0, clients_count;
612 SilcClientID *client_id = NULL;
613 SilcClientEntry *clients = NULL, entry;
616 /* Parse the whois request */
617 if (!silc_server_command_whois_parse(cmd, &client_id, &nick,
618 &server_name, &count))
621 /* Process the command request. Let's search for the requested client and
622 send reply to the requesting server. */
625 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
627 clients = silc_calloc(1, sizeof(*clients));
632 clients = silc_idlist_get_clients_by_nickname(server->local_list,
637 /* If we are router we will check our global list as well. */
638 if (!clients && server->server_type == SILC_ROUTER) {
640 entry = silc_idlist_find_client_by_id(server->global_list, client_id);
642 clients = silc_calloc(1, sizeof(*clients));
647 clients = silc_idlist_get_clients_by_nickname(server->global_list,
654 /* Such a client really does not exist in the SILC network. */
655 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
656 SILC_STATUS_ERR_NO_SUCH_NICK,
657 3, nick, strlen(nick));
661 /* Router always finds the client entry if it exists in the SILC network.
662 However, it might be incomplete entry and does not include all the
663 mandatory fields that WHOIS command reply requires. Check for these and
664 make query from the server who owns the client if some fields are
666 if (!cmd->pending && server->server_type == SILC_ROUTER &&
667 !silc_server_command_whois_check(cmd, clients, clients_count)) {
672 /* Send the command reply to the client */
673 silc_server_command_whois_send_reply(cmd, clients, clients_count);
679 silc_free(client_id);
683 silc_free(server_name);
688 /* Server side of command WHOIS. Processes user's query and sends found
689 results as command replies back to the client. */
691 SILC_SERVER_CMD_FUNC(whois)
693 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
696 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3);
698 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
699 ret = silc_server_command_whois_from_client(cmd);
701 ret = silc_server_command_whois_from_server(cmd);
704 silc_server_command_free(cmd);
707 SILC_SERVER_CMD_FUNC(whowas)
711 SILC_SERVER_CMD_FUNC(identify)
713 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
714 SilcServer server = cmd->server;
715 char *tmp, *nick = NULL, *server_name = NULL;
716 unsigned int argc, count = 0, len;
718 SilcClientID *client_id = NULL;
719 SilcClientEntry entry;
720 SilcBuffer packet, idp;
722 SILC_LOG_DEBUG(("Start"));
724 argc = silc_argument_get_arg_num(cmd->args);
726 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
727 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
731 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
732 SILC_STATUS_ERR_TOO_MANY_PARAMS);
736 /* If client ID is in the command it must be used instead of nickname */
737 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
740 /* Get the nickname@server string and parse it. */
741 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
743 if (strchr(tmp, '@')) {
744 len = strcspn(tmp, "@");
745 nick = silc_calloc(len + 1, sizeof(char));
746 memcpy(nick, tmp, len);
747 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
748 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
754 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
758 /* Command includes ID, use that */
759 client_id = silc_id_payload_parse_id(tmp, len);
763 /* Get the max count of reply messages allowed */
765 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
768 SILC_STATUS_ERR_TOO_MANY_PARAMS);
776 entry = silc_idlist_find_client_by_nickname(server->local_list,
779 entry = silc_idlist_find_client_by_hash(server->global_list,
780 nick, server->md5hash);
782 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
785 /* If client was not found and if we are normal server and are connected
786 to a router we will make global query from the router. */
787 if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
789 SilcBuffer buffer = cmd->packet->buffer;
791 SILC_LOG_DEBUG(("Requesting identify from router"));
793 /* Send IDENTIFY command to our router */
794 silc_buffer_push(buffer, buffer->data - buffer->head);
795 silc_server_packet_forward(server, (SilcSocketConnection)
796 server->router->connection,
797 buffer->data, buffer->len, TRUE);
801 /* If we are router we have checked our local list by nickname and our
802 global list by hash so far. It is possible that the client is still not
803 found and we'll check it from local list by hash. */
804 if (!entry && server->server_type == SILC_ROUTER)
805 entry = silc_idlist_find_client_by_hash(server->local_list,
806 nick, server->md5hash);
809 /* The client definitely does not exist */
810 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
811 SILC_STATUS_ERR_NO_SUCH_NICK,
812 3, tmp, strlen(tmp));
816 /* Send IDENTIFY reply */
817 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
818 tmp = silc_argument_get_first_arg(cmd->args, NULL);
819 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
820 SILC_STATUS_OK, 0, 2,
821 2, idp->data, idp->len,
822 3, nick, strlen(nick));
823 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
824 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
825 silc_server_packet_send_dest(server, cmd->sock,
826 SILC_PACKET_COMMAND_REPLY, 0,
827 id, cmd->packet->src_id_type,
828 packet->data, packet->len, FALSE);
831 silc_server_packet_send(server, cmd->sock,
832 SILC_PACKET_COMMAND_REPLY, 0,
833 packet->data, packet->len, FALSE);
836 silc_buffer_free(packet);
837 silc_buffer_free(idp);
839 silc_free(client_id);
845 silc_free(server_name);
846 silc_server_command_free(cmd);
849 /* Checks string for bad characters and returns TRUE if they are found. */
851 static int silc_server_command_bad_chars(char *nick)
853 if (strchr(nick, '\\')) return TRUE;
854 if (strchr(nick, '\"')) return TRUE;
855 if (strchr(nick, '´')) return TRUE;
856 if (strchr(nick, '`')) return TRUE;
857 if (strchr(nick, '\'')) return TRUE;
858 if (strchr(nick, '*')) return TRUE;
859 if (strchr(nick, '/')) return TRUE;
860 if (strchr(nick, '@')) return TRUE;
865 /* Server side of command NICK. Sets nickname for user. Setting
866 nickname causes generation of a new client ID for the client. The
867 new client ID is sent to the client after changing the nickname. */
869 SILC_SERVER_CMD_FUNC(nick)
871 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
872 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
873 SilcServer server = cmd->server;
874 SilcBuffer packet, nidp, oidp;
875 SilcClientID *new_id;
878 SILC_LOG_DEBUG(("Start"));
880 /* Check number of arguments */
881 if (silc_argument_get_arg_num(cmd->args) < 1) {
882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
883 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
888 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
889 if (silc_server_command_bad_chars(nick) == TRUE) {
890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
891 SILC_STATUS_ERR_BAD_NICKNAME);
895 /* Create new Client ID */
896 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
897 cmd->server->md5hash, nick,
900 /* Send notify about nickname change to our router. We send the new
901 ID and ask to replace it with the old one. If we are router the
902 packet is broadcasted. */
903 if (!cmd->server->standalone)
904 silc_server_send_replace_id(server, server->router->connection,
905 server->server_type == SILC_SERVER ?
906 FALSE : TRUE, client->id,
907 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
908 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
910 /* Remove old cache entry */
911 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
914 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
918 memset(client->id, 0, SILC_ID_CLIENT_LEN);
919 silc_free(client->id);
922 /* Save the nickname as this client is our local client */
923 if (client->nickname)
924 silc_free(client->nickname);
926 client->nickname = strdup(nick);
929 /* Update client cache */
930 silc_idcache_add(server->local_list->clients, client->nickname,
931 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
933 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
935 /* Send NICK_CHANGE notify */
936 silc_server_send_notify_on_channels(server, client,
937 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
938 oidp->data, oidp->len,
939 nidp->data, nidp->len);
941 /* Send the new Client ID as reply command back to client */
942 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
943 SILC_STATUS_OK, 0, 1,
944 2, nidp->data, nidp->len);
945 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
946 0, packet->data, packet->len, FALSE);
948 silc_buffer_free(packet);
949 silc_buffer_free(nidp);
950 silc_buffer_free(oidp);
953 silc_server_command_free(cmd);
956 SILC_SERVER_CMD_FUNC(list)
960 /* Server side of TOPIC command. Sets topic for channel and/or returns
961 current topic to client. */
963 SILC_SERVER_CMD_FUNC(topic)
965 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
966 SilcServer server = cmd->server;
967 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
968 SilcChannelID *channel_id;
969 SilcChannelEntry channel;
970 SilcChannelClientEntry chl;
971 SilcBuffer packet, idp;
973 unsigned int argc, tmp_len;
975 /* Check number of arguments */
976 argc = silc_argument_get_arg_num(cmd->args);
978 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
979 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
984 SILC_STATUS_ERR_TOO_MANY_PARAMS);
989 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
991 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
992 SILC_STATUS_ERR_NO_CHANNEL_ID);
995 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
997 /* Check whether the channel exists */
998 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1000 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1001 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1007 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1009 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1010 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1014 if (strlen(tmp) > 256) {
1015 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1016 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1020 /* See whether has rights to change topic */
1021 silc_list_start(channel->user_list);
1022 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1023 if (chl->client == client) {
1024 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1025 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1026 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1034 /* Set the topic for channel */
1036 silc_free(channel->topic);
1037 channel->topic = strdup(tmp);
1039 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1041 /* Send notify about topic change to all clients on the channel */
1042 silc_server_send_notify_to_channel(server, channel, TRUE,
1043 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1044 idp->data, idp->len,
1045 channel->topic, strlen(channel->topic));
1046 silc_buffer_free(idp);
1049 /* Send the topic to client as reply packet */
1050 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1052 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1053 SILC_STATUS_OK, 0, 2,
1054 2, idp->data, idp->len,
1056 strlen(channel->topic));
1058 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1059 SILC_STATUS_OK, 0, 1,
1060 2, idp->data, idp->len);
1061 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1062 0, packet->data, packet->len, FALSE);
1064 silc_buffer_free(packet);
1065 silc_buffer_free(idp);
1066 silc_free(channel_id);
1069 silc_server_command_free(cmd);
1072 /* Server side of INVITE command. Invites some client to join some channel. */
1074 SILC_SERVER_CMD_FUNC(invite)
1076 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1077 SilcServer server = cmd->server;
1078 SilcSocketConnection sock = cmd->sock, dest_sock;
1079 SilcClientEntry sender, dest;
1080 SilcClientID *dest_id;
1081 SilcChannelEntry channel;
1082 SilcChannelID *channel_id;
1085 unsigned int argc, len;
1087 /* Check number of arguments */
1088 argc = silc_argument_get_arg_num(cmd->args);
1090 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1091 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1095 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1096 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1100 /* Get destination ID */
1101 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1103 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1104 SILC_STATUS_ERR_NO_CLIENT_ID);
1107 dest_id = silc_id_payload_parse_id(tmp, len);
1109 /* Get Channel ID */
1110 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1112 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1113 SILC_STATUS_ERR_NO_CHANNEL_ID);
1116 channel_id = silc_id_payload_parse_id(tmp, len);
1118 /* Check whether the channel exists */
1119 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1122 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1126 /* Check whether the sender of this command is on the channel. */
1127 sender = (SilcClientEntry)sock->user_data;
1128 if (!silc_server_client_on_channel(sender, channel)) {
1129 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1130 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1134 /* Check whether the channel is invite-only channel. If yes then the
1135 sender of this command must be at least channel operator. */
1136 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1137 SilcChannelClientEntry chl;
1139 silc_list_start(channel->user_list);
1140 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1141 if (chl->client == sender) {
1142 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1143 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1144 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1151 /* Find the connection data for the destination. If it is local we will
1152 send it directly otherwise we will send it to router for routing. */
1153 dest = silc_idlist_find_client_by_id(server->local_list, dest_id);
1155 dest_sock = (SilcSocketConnection)dest->connection;
1157 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1159 /* Check whether the requested client is already on the channel. */
1160 /* XXX if we are normal server we don't know about global clients on
1161 the channel thus we must request it (NAMES command), check from
1162 local cache as well. */
1163 if (silc_server_client_on_channel(dest, channel)) {
1164 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1165 SILC_STATUS_ERR_USER_ON_CHANNEL);
1169 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1171 /* Send notify to the client that is invited to the channel */
1172 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1173 SILC_NOTIFY_TYPE_INVITE, 2,
1174 sidp->data, sidp->len, tmp, len);
1176 /* Send command reply */
1177 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1180 silc_buffer_free(sidp);
1183 silc_server_command_free(cmd);
1186 /* Quits connection to client. This gets called if client won't
1187 close the connection even when it has issued QUIT command. */
1189 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1191 SilcServer server = (SilcServer)context;
1192 SilcSocketConnection sock = server->sockets[fd];
1194 /* Free all client specific data, such as client entry and entires
1195 on channels this client may be on. */
1196 silc_server_free_sock_user_data(server, sock);
1198 /* Close the connection on our side */
1199 silc_server_close_connection(server, sock);
1202 /* Quits SILC session. This is the normal way to disconnect client. */
1204 SILC_SERVER_CMD_FUNC(quit)
1206 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1207 SilcServer server = cmd->server;
1208 SilcSocketConnection sock = cmd->sock;
1210 SILC_LOG_DEBUG(("Start"));
1212 /* We quit the connection with little timeout */
1213 silc_task_register(server->timeout_queue, sock->sock,
1214 silc_server_command_quit_cb, server,
1215 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1217 silc_server_command_free(cmd);
1220 SILC_SERVER_CMD_FUNC(kill)
1224 /* Server side of command INFO. This sends information about us to
1225 the client. If client requested specific server we will send the
1226 command to that server. */
1228 SILC_SERVER_CMD_FUNC(info)
1230 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1231 SilcServer server = cmd->server;
1232 SilcBuffer packet, idp;
1234 char info_string[256], *dest_server;
1236 argc = silc_argument_get_arg_num(cmd->args);
1238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1239 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1244 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1248 /* Get server name */
1249 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1251 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1252 SILC_STATUS_ERR_NO_SUCH_SERVER);
1256 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1257 /* Send our reply */
1258 memset(info_string, 0, sizeof(info_string));
1259 snprintf(info_string, sizeof(info_string),
1260 "location: %s server: %s admin: %s <%s>",
1261 server->config->admin_info->location,
1262 server->config->admin_info->server_type,
1263 server->config->admin_info->admin_name,
1264 server->config->admin_info->admin_email);
1266 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1268 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1269 SILC_STATUS_OK, 0, 2,
1270 2, idp->data, idp->len,
1272 strlen(info_string));
1273 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1274 packet->data, packet->len, FALSE);
1276 silc_buffer_free(packet);
1277 silc_buffer_free(idp);
1279 /* Send this command to the requested server */
1281 if (server->server_type == SILC_SERVER && !server->standalone) {
1285 if (server->server_type == SILC_ROUTER) {
1291 silc_server_command_free(cmd);
1294 SILC_SERVER_CMD_FUNC(connect)
1298 /* Server side of command PING. This just replies to the ping. */
1300 SILC_SERVER_CMD_FUNC(ping)
1302 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1303 SilcServer server = cmd->server;
1305 unsigned int argc, len;
1308 argc = silc_argument_get_arg_num(cmd->args);
1310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1311 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1316 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1321 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1323 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1324 SILC_STATUS_ERR_NO_SERVER_ID);
1327 id = silc_id_str2id(tmp, SILC_ID_SERVER);
1331 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1332 /* Send our reply */
1333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1337 SILC_STATUS_ERR_NO_SUCH_SERVER);
1344 silc_server_command_free(cmd);
1347 SILC_SERVER_CMD_FUNC(oper)
1356 SilcChannelEntry channel;
1358 SilcClientEntry client;
1359 } JoinInternalContext;
1361 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1363 JoinInternalContext *ctx = (JoinInternalContext *)context;
1365 if (ctx->channel->key && ctx->channel->key_len) {
1368 clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1370 silc_server_send_notify_to_channel(ctx->server, ctx->channel, FALSE,
1371 SILC_NOTIFY_TYPE_JOIN, 1,
1372 clidp->data, clidp->len);
1374 /* Send NEW_CHANNEL_USER packet to primary route */
1375 silc_server_send_new_channel_user(server, server->router->connection,
1376 server->server_type == SILC_SERVER ?
1378 channel->id, SILC_ID_CHANNEL_LEN,
1379 client->id, SILC_ID_CLIENT_LEN);
1382 /* Send NAMES command reply to the joined channel so the user sees who
1383 is currently on the channel. */
1384 silc_server_command_send_names(ctx->server, ctx->client->connection,
1387 silc_buffer_free(clidp);
1390 silc_task_register(ctx->server->timeout_queue, fd,
1391 silc_server_command_join_notify, context,
1392 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1396 /* Assembles NAMES command and executes it. This is called when client
1397 joins to a channel and we wan't to send NAMES command reply to the
1400 void silc_server_command_send_names(SilcServer server,
1401 SilcSocketConnection sock,
1402 SilcChannelEntry channel)
1404 SilcServerCommandContext cmd;
1405 SilcBuffer buffer, idp;
1407 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1408 buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1409 1, idp->data, idp->len);
1411 cmd = silc_calloc(1, sizeof(*cmd));
1412 cmd->payload = silc_command_payload_parse(buffer);
1413 cmd->args = silc_command_get_args(cmd->payload);
1414 cmd->server = server;
1416 cmd->pending = FALSE;
1418 silc_server_command_names((void *)cmd);
1423 /* Internal routine that is called after router has replied to server's
1424 JOIN command it forwarded to the router. The route has joined and possibly
1425 creaetd the channel. This function adds the client to the channel's user
1428 SILC_SERVER_CMD_FUNC(add_to_channel)
1430 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1431 SilcServer server = cmd->server;
1432 SilcClientEntry client;
1433 SilcChannelEntry channel;
1434 SilcChannelClientEntry chl;
1437 /* Get channel name */
1438 channel_name = silc_argument_get_arg_type(cmd->args, 1, NULL);
1440 /* Get client entry */
1441 client = (SilcClientEntry)cmd->sock->user_data;
1443 /* Get channel entry */
1444 channel = silc_idlist_find_channel_by_name(server->local_list, channel_name);
1446 /* Join the client to the channel by adding it to channel's user list.
1447 Add also the channel to client entry's channels list for fast cross-
1449 chl = silc_calloc(1, sizeof(*chl));
1450 //chl->mode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
1451 chl->client = client;
1452 chl->channel = channel;
1453 silc_list_add(channel->user_list, chl);
1454 silc_list_add(client->channels, chl);
1457 silc_server_command_free(cmd);
1460 /* Internal routine to join channel. The channel sent to this function
1461 has been either created or resolved from ID lists. This joins the sent
1462 client to the channel. */
1464 static void silc_server_command_join_channel(SilcServer server,
1465 SilcServerCommandContext cmd,
1466 SilcChannelEntry channel,
1470 SilcSocketConnection sock = cmd->sock;
1472 unsigned int tmp_len;
1473 unsigned char *passphrase = NULL, mode[4];
1474 SilcClientEntry client;
1475 SilcChannelClientEntry chl;
1476 SilcBuffer reply, chidp, clidp;
1481 /* Get passphrase */
1482 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1484 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1485 memcpy(passphrase, tmp, tmp_len);
1489 * Check channel modes
1492 /* Check invite list if channel is invite-only channel */
1493 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1494 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1495 /* Invite list is specified. Check whether client is invited in the
1496 list. If not, then check whether it has been invited otherwise. */
1499 /* XXX client must be invited to be able to join the channel */
1503 /* Check ban list if set */
1504 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1508 /* Check the channel passphrase if set. */
1509 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1510 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1511 strlen(channel->mode_data.passphrase))) {
1512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1513 SILC_STATUS_ERR_BAD_PASSWORD);
1518 /* Check user count limit if set. */
1519 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1520 if (silc_list_count(channel->user_list) + 1 >
1521 channel->mode_data.user_limit) {
1522 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1523 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1529 * Client is allowed to join to the channel. Make it happen.
1532 /* If the JOIN request was forwarded to us we will make a bit slower
1533 query to get the client pointer. Otherwise, we get the client pointer
1535 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1536 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1537 client = silc_idlist_find_client_by_id(server->local_list, id);
1540 SILC_LOG_ERROR(("Forwarded join command did not find the client who "
1541 "wanted to join the channel"));
1546 client = (SilcClientEntry)sock->user_data;
1549 /* Check whether the client already is on the channel */
1550 if (silc_server_client_on_channel(client, channel)) {
1551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1552 SILC_STATUS_ERR_USER_ON_CHANNEL);
1556 /* Generate new channel key as protocol dictates */
1558 silc_server_create_channel_key(server, channel, 0);
1560 /* Join the client to the channel by adding it to channel's user list.
1561 Add also the channel to client entry's channels list for fast cross-
1563 chl = silc_calloc(1, sizeof(*chl));
1565 chl->client = client;
1566 chl->channel = channel;
1567 silc_list_add(channel->user_list, chl);
1568 silc_list_add(client->channels, chl);
1570 /* Encode Client ID Payload of the original client who wants to join */
1571 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1573 /* Encode command reply packet */
1574 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1575 SILC_PUT32_MSB(channel->mode, mode);
1576 if (!channel->topic) {
1578 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1579 SILC_STATUS_OK, 0, 3,
1580 2, channel->channel_name,
1581 strlen(channel->channel_name),
1582 3, chidp->data, chidp->len,
1586 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1587 SILC_STATUS_OK, 0, 4,
1588 2, channel->channel_name,
1589 strlen(channel->channel_name),
1590 3, chidp->data, chidp->len,
1593 strlen(channel->topic));
1596 if (server->server_type == SILC_ROUTER &&
1597 cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1598 /* We are router and server has forwarded this command to us. Send
1599 all replys to the server. */
1602 /* Send command reply destined to the original client */
1603 tmpid = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1604 silc_server_packet_send_dest(cmd->server, sock,
1605 SILC_PACKET_COMMAND_REPLY, 0,
1606 tmpid, cmd->packet->src_id_type,
1607 reply->data, reply->len, FALSE);
1609 /* Distribute new channel key to local cell and local clients. */
1610 silc_server_send_channel_key(server, channel, FALSE);
1612 /* Distribute JOIN notify into the cell for everbody on the channel */
1613 silc_server_send_notify_to_channel(server, channel, FALSE,
1614 SILC_NOTIFY_TYPE_JOIN, 1,
1615 clidp->data, clidp->len);
1617 /* Broadcast NEW_CHANNEL_USER packet to primary route */
1618 silc_server_send_new_channel_user(server, server->router->connection,
1619 TRUE, channel->id, SILC_ID_CHANNEL_LEN,
1620 client->id, SILC_ID_CLIENT_LEN);
1624 /* Client sent the command. Send all replies directly to the client. */
1626 /* Send command reply */
1627 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1628 reply->data, reply->len, FALSE);
1630 /* Send the channel key. Channel key is sent before any other packet
1632 silc_server_send_channel_key(server, channel, server->standalone ?
1635 /* Send JOIN notify to locally connected clients on the channel */
1636 silc_server_send_notify_to_channel(server, channel, FALSE,
1637 SILC_NOTIFY_TYPE_JOIN, 1,
1638 clidp->data, clidp->len);
1640 /* Send NEW_CHANNEL_USER packet to our primary router */
1641 if (!server->standalone)
1642 silc_server_send_new_channel_user(server, server->router->connection,
1644 channel->id, SILC_ID_CHANNEL_LEN,
1645 client->id, SILC_ID_CLIENT_LEN);
1647 /* Send NAMES command reply to the joined channel so the user sees who
1648 is currently on the channel. */
1649 silc_server_command_send_names(server, sock, channel);
1652 silc_buffer_free(reply);
1653 silc_buffer_free(clidp);
1654 silc_buffer_free(chidp);
1658 silc_free(passphrase);
1661 /* Server side of command JOIN. Joins client into requested channel. If
1662 the channel does not exist it will be created. */
1664 SILC_SERVER_CMD_FUNC(join)
1666 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1667 SilcServer server = cmd->server;
1669 char *tmp, *channel_name = NULL, *cipher = NULL;
1670 SilcChannelEntry channel;
1671 unsigned int umode = 0;
1672 int created = FALSE;
1674 SILC_LOG_DEBUG(("Start"));
1676 /* Check number of parameters */
1677 argc = silc_argument_get_arg_num(cmd->args);
1679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1680 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1685 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1689 /* Get channel name */
1690 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1693 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1698 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1699 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1700 SILC_STATUS_ERR_BAD_CHANNEL);
1701 silc_free(channel_name);
1705 /* Get cipher name */
1706 cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1708 /* See if the channel exists */
1709 channel = silc_idlist_find_channel_by_name(server->local_list, channel_name);
1711 /* Channel not found */
1713 /* If we are standalone server we don't have a router, we just create
1714 the channel by ourselves. */
1715 if (server->standalone) {
1716 channel = silc_server_create_new_channel(server, server->id, cipher,
1718 umode |= SILC_CHANNEL_UMODE_CHANOP;
1719 umode |= SILC_CHANNEL_UMODE_CHANFO;
1723 /* The channel does not exist on our server. If we are normal server
1724 we will send JOIN command to our router which will handle the joining
1725 procedure (either creates the channel if it doesn't exist or joins
1726 the client to it). */
1727 if (server->server_type == SILC_SERVER) {
1728 /* Forward the original JOIN command to the router */
1729 silc_buffer_push(cmd->packet->buffer,
1730 cmd->packet->buffer->data -
1731 cmd->packet->buffer->head);
1732 silc_server_packet_forward(server, (SilcSocketConnection)
1733 server->router->connection,
1734 cmd->packet->buffer->data,
1735 cmd->packet->buffer->len, TRUE);
1737 /* Register handler that will be called after the router has replied
1738 to us. We will add the client to the new channel in this callback
1739 function. Will be called from JOIN command reply. */
1740 silc_server_command_pending(server, SILC_COMMAND_JOIN,
1741 ++server->router->data.cmd_ident,
1742 silc_server_command_add_to_channel,
1747 /* We are router and the channel does not seem exist so we will check
1748 our global list as well for the channel. */
1749 channel = silc_idlist_find_channel_by_name(server->global_list,
1752 /* Channel really does not exist, create it */
1753 channel = silc_server_create_new_channel(server, server->id, cipher,
1755 umode |= SILC_CHANNEL_UMODE_CHANOP;
1756 umode |= SILC_CHANNEL_UMODE_CHANFO;
1762 /* Join to the channel */
1763 silc_server_command_join_channel(server, cmd, channel, created, umode);
1766 silc_server_command_free(cmd);
1769 /* Server side of command MOTD. Sends server's current "message of the
1770 day" to the client. */
1772 SILC_SERVER_CMD_FUNC(motd)
1774 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1775 SilcServer server = cmd->server;
1780 SILC_LOG_DEBUG(("Start"));
1782 argc = silc_argument_get_arg_num(cmd->args);
1784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1785 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1789 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1790 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1794 /* XXX show currently only our motd */
1796 if (server->config && server->config->motd &&
1797 server->config->motd->motd_file) {
1800 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
1805 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
1811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
1816 silc_server_command_free(cmd);
1819 SILC_SERVER_CMD_FUNC(umode)
1823 /* Checks that client has rights to add or remove channel modes. If any
1824 of the checks fails FALSE is returned. */
1826 int silc_server_check_cmode_rights(SilcChannelEntry channel,
1827 SilcChannelClientEntry client,
1830 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1831 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1833 /* Check whether has rights to change anything */
1834 if (!is_op && !is_fo)
1837 /* Check whether has rights to change everything */
1841 /* We know that client is channel operator, check that they are not
1842 changing anything that requires channel founder rights. Rest of the
1843 modes are available automatically for channel operator. */
1845 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1846 if (is_op && !is_fo)
1849 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1850 if (is_op && !is_fo)
1855 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1856 if (is_op && !is_fo)
1859 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1860 if (is_op && !is_fo)
1865 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1866 if (is_op && !is_fo)
1869 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1870 if (is_op && !is_fo)
1878 /* Server side command of CMODE. Changes channel mode */
1880 SILC_SERVER_CMD_FUNC(cmode)
1882 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1883 SilcServer server = cmd->server;
1884 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1885 SilcChannelID *channel_id;
1886 SilcChannelEntry channel;
1887 SilcChannelClientEntry chl;
1888 SilcBuffer packet, cidp;
1889 unsigned char *tmp, *tmp_id, *tmp_mask;
1890 unsigned int argc, mode_mask, tmp_len, tmp_len2;
1892 SILC_LOG_DEBUG(("Start"));
1894 argc = silc_argument_get_arg_num(cmd->args);
1896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1897 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1902 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1906 /* Get Channel ID */
1907 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
1909 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1910 SILC_STATUS_ERR_NO_CHANNEL_ID);
1913 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
1915 /* Get the channel mode mask */
1916 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1918 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1919 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1922 SILC_GET32_MSB(mode_mask, tmp_mask);
1924 /* Get channel entry */
1925 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1927 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1928 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1932 /* Check whether this client is on the channel */
1933 if (!silc_server_client_on_channel(client, channel)) {
1934 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1935 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1939 /* Get entry to the channel user list */
1940 silc_list_start(channel->user_list);
1941 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1942 if (chl->client == client)
1945 /* Check that client has rights to change any requested channel modes */
1946 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
1947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1948 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1953 * Check the modes. Modes that requires nothing special operation are
1957 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
1958 /* Channel uses private keys to protect traffic. Client(s) has set the
1959 key locally they want to use, server does not know that key. */
1960 /* Nothing interesting to do here now */
1962 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1963 /* The mode is removed and we need to generate and distribute
1964 new channel key. Clients are not using private channel keys
1965 anymore after this. */
1967 /* XXX Duplicated code, make own function for this!! LEAVE uses this
1970 /* Re-generate channel key */
1971 silc_server_create_channel_key(server, channel, 0);
1973 /* Encode channel key payload to be distributed on the channel */
1975 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1976 strlen(channel->channel_key->
1978 channel->channel_key->cipher->name,
1979 channel->key_len / 8, channel->key);
1981 /* If we are normal server then we will send it to our router. If we
1982 are router we will send it to all local servers that has clients on
1984 if (server->server_type == SILC_SERVER) {
1985 if (!server->standalone)
1986 silc_server_packet_send(server,
1987 cmd->server->router->connection,
1988 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1994 /* Send to locally connected clients on the channel */
1995 silc_server_packet_send_local_channel(server, channel,
1996 SILC_PACKET_CHANNEL_KEY, 0,
1997 packet->data, packet->len, FALSE);
1998 silc_buffer_free(packet);
2002 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2003 /* User limit is set on channel */
2004 unsigned int user_limit;
2006 /* Get user limit */
2007 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2009 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2010 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2011 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2015 SILC_GET32_MSB(user_limit, tmp);
2016 channel->mode_data.user_limit = user_limit;
2019 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2020 /* User limit mode is unset. Remove user limit */
2021 channel->mode_data.user_limit = 0;
2024 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2025 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2026 /* Passphrase has been set to channel */
2028 /* Get the passphrase */
2029 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2031 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2032 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2036 /* Save the passphrase */
2037 channel->mode_data.passphrase = strdup(tmp);
2040 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2041 /* Passphrase mode is unset. remove the passphrase */
2042 if (channel->mode_data.passphrase) {
2043 silc_free(channel->mode_data.passphrase);
2044 channel->mode_data.passphrase = NULL;
2049 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2050 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2051 /* Ban list is specified for channel */
2054 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2057 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2061 /* XXX check that channel founder is not banned */
2063 /* Save the ban list */
2064 channel->mode_data.ban_list = strdup(tmp);
2067 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2068 /* Ban mode is unset. Remove the entire ban list */
2069 if (channel->mode_data.ban_list) {
2070 silc_free(channel->mode_data.ban_list);
2071 channel->mode_data.ban_list = NULL;
2076 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2077 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2078 /* Invite list is specified for channel */
2080 /* Get invite list */
2081 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2083 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2084 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2088 /* Save the invite linst */
2089 channel->mode_data.invite_list = strdup(tmp);
2092 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2093 /* Invite list mode is unset. Remove the entire invite list */
2094 if (channel->mode_data.invite_list) {
2095 silc_free(channel->mode_data.invite_list);
2096 channel->mode_data.invite_list = NULL;
2101 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2102 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2103 /* Cipher to use protect the traffic */
2104 unsigned int key_len = 128;
2108 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2111 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2115 cp = strchr(tmp, ':');
2121 /* XXX Duplicated code, make own function for this!! */
2123 /* Delete old cipher and allocate the new one */
2124 silc_cipher_free(channel->channel_key);
2125 silc_cipher_alloc(tmp, &channel->channel_key);
2131 /* Re-generate channel key */
2132 silc_server_create_channel_key(server, channel, key_len);
2134 /* Encode channel key payload to be distributed on the channel */
2136 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2137 strlen(channel->channel_key->
2139 channel->channel_key->cipher->name,
2140 channel->key_len / 8, channel->key);
2142 /* If we are normal server then we will send it to our router. If we
2143 are router we will send it to all local servers that has clients on
2145 if (server->server_type == SILC_SERVER) {
2146 if (!server->standalone)
2147 silc_server_packet_send(server,
2148 cmd->server->router->connection,
2149 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2155 /* Send to locally connected clients on the channel */
2156 silc_server_packet_send_local_channel(server, channel,
2157 SILC_PACKET_CHANNEL_KEY, 0,
2158 packet->data, packet->len, FALSE);
2159 silc_buffer_free(packet);
2162 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2163 /* Cipher mode is unset. Remove the cipher and revert back to
2166 if (channel->mode_data.cipher) {
2167 silc_free(channel->mode_data.cipher);
2168 channel->mode_data.cipher = NULL;
2169 channel->mode_data.key_len = 0;
2172 /* Generate new cipher and key for the channel */
2174 /* XXX Duplicated code, make own function for this!! */
2176 /* Delete old cipher and allocate default one */
2177 silc_cipher_free(channel->channel_key);
2178 if (!channel->cipher)
2179 silc_cipher_alloc("twofish", &channel->channel_key);
2181 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2183 /* Re-generate channel key */
2184 silc_server_create_channel_key(server, channel, 0);
2186 /* Encode channel key payload to be distributed on the channel */
2188 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2189 strlen(channel->channel_key->
2191 channel->channel_key->cipher->name,
2192 channel->key_len / 8, channel->key);
2194 /* If we are normal server then we will send it to our router. If we
2195 are router we will send it to all local servers that has clients on
2197 if (server->server_type == SILC_SERVER) {
2198 if (!server->standalone)
2199 silc_server_packet_send(server,
2200 cmd->server->router->connection,
2201 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2207 /* Send to locally connected clients on the channel */
2208 silc_server_packet_send_local_channel(server, channel,
2209 SILC_PACKET_CHANNEL_KEY, 0,
2210 packet->data, packet->len, FALSE);
2211 silc_buffer_free(packet);
2215 /* Finally, set the mode */
2216 channel->mode = mode_mask;
2218 /* Send CMODE_CHANGE notify */
2219 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2220 silc_server_send_notify_to_channel(server, channel, TRUE,
2221 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2222 cidp->data, cidp->len,
2226 /* Send command reply to sender */
2227 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2228 SILC_STATUS_OK, 0, 1,
2230 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2231 packet->data, packet->len, FALSE);
2233 silc_buffer_free(packet);
2234 silc_free(channel_id);
2237 silc_server_command_free(cmd);
2240 /* Server side of CUMODE command. Changes client's mode on a channel. */
2242 SILC_SERVER_CMD_FUNC(cumode)
2244 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2245 SilcServer server = cmd->server;
2246 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2247 SilcChannelID *channel_id;
2248 SilcClientID *client_id;
2249 SilcChannelEntry channel;
2250 SilcClientEntry target_client;
2251 SilcChannelClientEntry chl;
2252 SilcBuffer packet, idp;
2253 unsigned char *tmp_id, *tmp_mask;
2254 unsigned int argc, target_mask, sender_mask, tmp_len;
2257 SILC_LOG_DEBUG(("Start"));
2259 argc = silc_argument_get_arg_num(cmd->args);
2261 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2262 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2267 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2271 /* Get Channel ID */
2272 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2274 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2275 SILC_STATUS_ERR_NO_CHANNEL_ID);
2278 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2280 /* Get channel entry */
2281 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
2283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2284 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2288 /* Check whether sender is on the channel */
2289 if (!silc_server_client_on_channel(client, channel)) {
2290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2291 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2295 /* Check that client has rights to change other's rights */
2296 silc_list_start(channel->user_list);
2297 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2298 if (chl->client == client) {
2299 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2300 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2302 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2306 sender_mask = chl->mode;
2311 /* Get the target client's channel mode mask */
2312 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2314 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2315 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2318 SILC_GET32_MSB(target_mask, tmp_mask);
2320 /* Get target Client ID */
2321 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2323 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2324 SILC_STATUS_ERR_NO_CHANNEL_ID);
2327 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2329 /* Get target client's entry */
2330 target_client = silc_idlist_find_client_by_id(server->local_list, client_id);
2331 if (!target_client) {
2332 /* XXX If target client is not one of mine send to primary route */
2335 /* Check whether target client is on the channel */
2336 if (!silc_server_client_on_channel(target_client, channel)) {
2337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2338 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2342 /* Get entry to the channel user list */
2343 silc_list_start(channel->user_list);
2344 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2345 if (chl->client == target_client)
2352 /* If the target client is founder, no one else can change their mode
2354 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2355 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2356 SILC_STATUS_ERR_NOT_YOU);
2360 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2361 /* Cannot promote anyone to channel founder */
2362 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2363 SILC_STATUS_ERR_NOT_YOU);
2366 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2367 if (target_client == client) {
2368 /* Remove channel founder rights from itself */
2369 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2373 SILC_STATUS_ERR_NOT_YOU);
2379 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2380 /* Promote to operator */
2381 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2382 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2386 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2387 /* Demote to normal user */
2388 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2393 /* Send notify to channel, notify only if mode was actually changed. */
2395 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2396 silc_server_send_notify_to_channel(server, channel, TRUE,
2397 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2398 idp->data, idp->len,
2399 tmp_mask, 4, tmp_id, tmp_len);
2400 silc_buffer_free(idp);
2403 /* Send command reply to sender */
2404 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2405 SILC_STATUS_OK, 0, 2,
2407 3, tmp_id, tmp_len);
2408 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2409 packet->data, packet->len, FALSE);
2411 silc_buffer_free(packet);
2412 silc_free(channel_id);
2413 silc_free(client_id);
2416 silc_server_command_free(cmd);
2419 /* Server side of KICK command. Kicks client out of channel. */
2421 SILC_SERVER_CMD_FUNC(kick)
2425 SILC_SERVER_CMD_FUNC(restart)
2429 SILC_SERVER_CMD_FUNC(close)
2433 SILC_SERVER_CMD_FUNC(die)
2437 SILC_SERVER_CMD_FUNC(silcoper)
2441 /* Server side command of LEAVE. Removes client from a channel. */
2443 SILC_SERVER_CMD_FUNC(leave)
2445 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2446 SilcServer server = cmd->server;
2447 SilcSocketConnection sock = cmd->sock;
2448 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2450 SilcChannelEntry channel;
2452 unsigned int i, argc, len;
2455 SILC_LOG_DEBUG(("Start"));
2457 argc = silc_argument_get_arg_num(cmd->args);
2459 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2460 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2464 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2465 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2469 /* Get Channel ID */
2470 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2472 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2473 SILC_STATUS_ERR_NO_CHANNEL_ID);
2476 id = silc_id_payload_parse_id(tmp, len);
2478 /* Get channel entry */
2479 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2481 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2482 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2486 /* Check whether this client is on the channel */
2487 if (!silc_server_client_on_channel(id_entry, channel)) {
2488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2489 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2493 /* Notify routers that they should remove this client from their list
2494 of clients on the channel. */
2495 if (!server->standalone)
2496 silc_server_send_remove_channel_user(server,
2497 server->router->connection,
2498 server->server_type == SILC_ROUTER ?
2499 TRUE : FALSE, id_entry->id, id);
2501 /* Remove client from channel */
2502 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2507 /* If the channel does not exist anymore we won't send anything */
2511 /* Re-generate channel key */
2512 silc_server_create_channel_key(server, channel, 0);
2514 /* Encode channel key payload to be distributed on the channel */
2516 silc_channel_key_payload_encode(len, tmp,
2517 strlen(channel->channel_key->cipher->name),
2518 channel->channel_key->cipher->name,
2519 channel->key_len / 8, channel->key);
2521 /* If we are normal server then we will send it to our router. If we
2522 are router we will send it to all local servers that has clients on
2524 if (server->server_type == SILC_SERVER) {
2525 if (!server->standalone)
2526 silc_server_packet_send(server,
2527 cmd->server->router->connection,
2528 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2534 /* Send to locally connected clients on the channel */
2535 silc_server_packet_send_local_channel(server, channel,
2536 SILC_PACKET_CHANNEL_KEY, 0,
2537 packet->data, packet->len, FALSE);
2539 silc_buffer_free(packet);
2543 silc_server_command_free(cmd);
2546 /* Server side of command NAMES. Resolves clients and their names currently
2547 joined on the requested channel. The name list is sent back to the
2550 SILC_SERVER_CMD_FUNC(names)
2552 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2553 SilcServer server = cmd->server;
2554 SilcChannelEntry channel;
2555 SilcChannelClientEntry chl;
2558 unsigned int i, len, len2, tmp_len, argc;
2560 char *name_list = NULL, *n;
2561 SilcBuffer client_id_list;
2562 SilcBuffer client_mode_list;
2564 SILC_LOG_DEBUG(("Start"));
2566 argc = silc_argument_get_arg_num(cmd->args);
2568 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2569 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2573 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2574 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2578 /* Get Channel ID */
2579 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2581 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2582 SILC_STATUS_ERR_NO_CHANNEL_ID);
2585 id = silc_id_payload_parse_id(tmp, tmp_len);
2587 /* Check whether the channel exists. If we are normal server and the
2588 channel does not exist we will send this same command to our router
2589 which will know if the channel exists. */
2590 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2592 if (server->server_type == SILC_SERVER && !server->standalone) {
2593 /* XXX Send names command */
2595 cmd->pending = TRUE;
2596 silc_server_command_pending(server, SILC_COMMAND_NAMES, 0,
2597 silc_server_command_names, context);
2601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2602 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2606 /* Assemble the name list now */
2609 silc_list_start(channel->user_list);
2611 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2612 n = chl->client->nickname;
2616 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2617 memcpy(name_list + (len - len2), n, len2);
2620 if (i == silc_list_count(channel->user_list) - 1)
2622 memcpy(name_list + len, ",", 1);
2630 /* Assemble the Client ID list now */
2631 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2632 silc_list_count(channel->user_list));
2633 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2634 silc_list_start(channel->user_list);
2635 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2638 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2639 silc_buffer_format(client_id_list,
2640 SILC_STR_UI_XNSTRING(idp->data, idp->len),
2642 silc_buffer_pull(client_id_list, idp->len);
2643 silc_buffer_free(idp);
2645 silc_buffer_push(client_id_list,
2646 client_id_list->data - client_id_list->head);
2648 /* Assemble mode list */
2649 client_mode_list = silc_buffer_alloc(4 *
2650 silc_list_count(channel->user_list));
2651 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2652 silc_list_start(channel->user_list);
2653 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2654 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2655 silc_buffer_pull(client_mode_list, 4);
2657 silc_buffer_push(client_mode_list,
2658 client_mode_list->data - client_mode_list->head);
2661 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2662 SILC_STATUS_OK, 0, 4,
2666 4, client_id_list->data,
2667 client_id_list->len,
2668 5, client_mode_list->data,
2669 client_mode_list->len);
2670 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2671 packet->data, packet->len, FALSE);
2673 silc_buffer_free(packet);
2674 silc_free(name_list);
2675 silc_buffer_free(client_id_list);
2676 silc_buffer_free(client_mode_list);
2680 silc_server_command_free(cmd);