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_users(SilcServer server,
42 SilcSocketConnection sock,
43 SilcChannelEntry channel,
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
49 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
54 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(connect, CONNECT,
60 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
69 SILC_SERVER_CMD(restart, RESTART,
70 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
71 SILC_SERVER_CMD(close, CLOSE,
72 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
73 SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
74 SILC_SERVER_CMD(silcoper, SILCOPER,
75 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
77 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
82 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
84 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
86 SILC_LOG_DEBUG(("Start")); \
89 silc_server_command_send_status_reply(cmd, command, \
90 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
91 silc_server_command_free(cmd); \
95 silc_server_command_send_status_reply(cmd, command, \
96 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
97 silc_server_command_free(cmd); \
102 /* Returns TRUE if the connection is registered. Unregistered connections
103 usually cannot send commands hence the check. */
105 static int silc_server_is_registered(SilcServer server,
106 SilcSocketConnection sock,
107 SilcServerCommandContext cmd,
110 SilcIDListData idata = (SilcIDListData)sock->user_data;
111 if (idata->registered)
114 silc_server_command_send_status_reply(cmd, command,
115 SILC_STATUS_ERR_NOT_REGISTERED);
116 silc_server_command_free(cmd);
120 /* Processes received command packet. */
122 void silc_server_command_process(SilcServer server,
123 SilcSocketConnection sock,
124 SilcPacketContext *packet)
126 SilcServerCommandContext ctx;
127 SilcServerCommand *cmd;
130 /* XXX allow commands in but do not execute them more than once per
133 /* Check whether it is allowed for this connection to execute any
135 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
137 SilcClientEntry client = (SilcClientEntry)sock->user_data;
142 /* Allow only one command executed in 2 seconds. */
143 curtime = time(NULL);
144 if (client->last_command && (curtime - client->last_command) < 2)
147 /* Update access time */
148 client->last_command = curtime;
152 /* Allocate command context. This must be free'd by the
153 command routine receiving it. */
154 ctx = silc_calloc(1, sizeof(*ctx));
155 ctx->server = server;
157 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
159 /* Parse the command payload in the packet */
160 ctx->payload = silc_command_payload_parse(packet->buffer);
162 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
163 silc_buffer_free(packet->buffer);
164 silc_packet_context_free(packet);
168 ctx->args = silc_command_get_args(ctx->payload);
170 /* Execute command. If this fails the packet is dropped. */
171 for (cmd = silc_command_list; cmd->cb; cmd++)
172 if (cmd->cmd == silc_command_get(ctx->payload)) {
174 if (!(cmd->flags & SILC_CF_REG)) {
179 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
186 SILC_LOG_ERROR(("Unknown command, packet dropped"));
187 silc_server_command_free(ctx);
192 /* Add new pending command to be executed when reply to a command has been
193 received. The `reply_cmd' is the command that will call the `callback'
194 with `context' when reply has been received. If `ident' is non-zero
195 the `callback' will be executed when received reply with command
196 identifier `ident'. */
198 void silc_server_command_pending(SilcServer server,
199 SilcCommand reply_cmd,
200 unsigned short ident,
201 SilcCommandCb callback,
204 SilcServerCommandPending *reply;
206 reply = silc_calloc(1, sizeof(*reply));
207 reply->reply_cmd = reply_cmd;
208 reply->ident = ident;
209 reply->context = context;
210 reply->callback = callback;
211 silc_dlist_add(server->pending_commands, reply);
214 /* Deletes pending command by reply command type. */
216 void silc_server_command_pending_del(SilcServer server,
217 SilcCommand reply_cmd,
218 unsigned short ident)
220 SilcServerCommandPending *r;
222 silc_dlist_start(server->pending_commands);
223 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
224 if (r->reply_cmd == reply_cmd && r->ident == ident) {
225 silc_dlist_del(server->pending_commands, r);
231 /* Checks for pending commands and marks callbacks to be called from
232 the command reply function. Returns TRUE if there were pending command. */
234 int silc_server_command_pending_check(SilcServer server,
235 SilcServerCommandReplyContext ctx,
237 unsigned short ident)
239 SilcServerCommandPending *r;
241 silc_dlist_start(server->pending_commands);
242 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
243 if (r->reply_cmd == command && r->ident == ident) {
244 ctx->context = r->context;
245 ctx->callback = r->callback;
254 /* Free's the command context allocated before executing the command */
256 static void silc_server_command_free(SilcServerCommandContext cmd)
260 silc_command_free_payload(cmd->payload);
262 silc_packet_context_free(cmd->packet);
267 /* Sends simple status message as command reply packet */
270 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
272 SilcCommandStatus status)
276 SILC_LOG_DEBUG(("Sending command status %d", status));
278 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
279 silc_server_packet_send(cmd->server, cmd->sock,
280 SILC_PACKET_COMMAND_REPLY, 0,
281 buffer->data, buffer->len, FALSE);
282 silc_buffer_free(buffer);
285 /* Sends command status reply with one extra argument. The argument
286 type must be sent as argument. */
289 silc_server_command_send_status_data(SilcServerCommandContext cmd,
291 SilcCommandStatus status,
292 unsigned int arg_type,
294 unsigned int arg_len)
298 SILC_LOG_DEBUG(("Sending command status %d", status));
300 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
301 arg_type, arg, arg_len);
302 silc_server_packet_send(cmd->server, cmd->sock,
303 SILC_PACKET_COMMAND_REPLY, 0,
304 buffer->data, buffer->len, FALSE);
305 silc_buffer_free(buffer);
308 /******************************************************************************
312 ******************************************************************************/
315 silc_server_command_whois_parse(SilcServerCommandContext cmd,
316 SilcClientID ***client_id,
317 unsigned int *client_id_count,
325 unsigned int argc = silc_argument_get_arg_num(cmd->args);
328 /* If client ID is in the command it must be used instead of nickname */
329 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
331 /* No ID, get the nickname@server string and parse it. */
332 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
334 if (strchr(tmp, '@')) {
335 len = strcspn(tmp, "@");
336 *nickname = silc_calloc(len + 1, sizeof(char));
337 memcpy(*nickname, tmp, len);
338 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
339 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
341 *nickname = strdup(tmp);
344 silc_server_command_send_status_reply(cmd, command,
345 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
349 /* Command includes ID, we must use that. Also check whether the command
350 has more than one ID set - take them all. */
352 *client_id = silc_calloc(1, sizeof(**client_id));
353 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
354 *client_id_count = 1;
356 /* Take all ID's from the command packet */
358 for (k = 1, i = 4; i < argc; i++) {
359 tmp = silc_argument_get_arg_type(cmd->args, i, &len);
361 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
362 (*client_id_count + 1));
363 (*client_id)[k++] = silc_id_payload_parse_id(tmp, len);
364 (*client_id_count)++;
369 /* Command includes ID, use that */
372 /* Get the max count of reply messages allowed */
373 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
383 silc_server_command_whois_check(SilcServerCommandContext cmd,
384 SilcClientEntry *clients,
385 unsigned int clients_count)
387 SilcServer server = cmd->server;
389 SilcClientEntry entry;
391 for (i = 0; i < clients_count; i++) {
394 if (!entry->nickname || !entry->username || !entry->userinfo) {
396 unsigned short old_ident;
401 old_ident = silc_command_get_ident(cmd->payload);
402 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
403 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
405 /* Send WHOIS command */
406 silc_server_packet_send(server, entry->router->connection,
407 SILC_PACKET_COMMAND, cmd->packet->flags,
408 tmpbuf->data, tmpbuf->len, TRUE);
410 /* Reprocess this packet after received reply */
411 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
412 silc_command_get_ident(cmd->payload),
413 silc_server_command_whois, (void *)cmd);
416 silc_command_set_ident(cmd->payload, old_ident);
418 silc_buffer_free(tmpbuf);
427 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
428 SilcClientEntry *clients,
429 unsigned int clients_count)
431 SilcServer server = cmd->server;
433 int i, count = 0, len;
434 SilcBuffer packet, idp;
435 SilcClientEntry entry;
436 SilcCommandStatus status;
437 unsigned short ident = silc_command_get_ident(cmd->payload);
439 status = SILC_STATUS_OK;
440 if (clients_count > 1)
441 status = SILC_STATUS_LIST_START;
443 for (i = 0; i < clients_count; i++) {
446 if (count && i - 1 == count)
449 if (clients_count > 2)
450 status = SILC_STATUS_LIST_ITEM;
452 if (clients_count > 1 && i == clients_count - 1)
453 status = SILC_STATUS_LIST_END;
455 /* Send WHOIS reply */
456 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
457 tmp = silc_argument_get_first_arg(cmd->args, NULL);
461 char nh[256], uh[256];
462 unsigned char idle[4];
463 SilcSocketConnection hsock;
465 memset(uh, 0, sizeof(uh));
466 memset(nh, 0, sizeof(nh));
468 strncat(nh, entry->nickname, strlen(entry->nickname));
469 if (!strchr(entry->nickname, '@')) {
471 len = entry->router ? strlen(entry->router->server_name) :
472 strlen(server->server_name);
473 strncat(nh, entry->router ? entry->router->server_name :
474 server->server_name, len);
477 strncat(uh, entry->username, strlen(entry->username));
478 if (!strchr(entry->username, '@')) {
480 hsock = (SilcSocketConnection)entry->connection;
481 len = strlen(hsock->hostname);
482 strncat(uh, hsock->hostname, len);
485 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
490 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
492 2, idp->data, idp->len,
496 strlen(entry->userinfo),
500 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
502 2, idp->data, idp->len,
508 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
509 0, packet->data, packet->len, FALSE);
511 silc_buffer_free(packet);
512 silc_buffer_free(idp);
517 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
519 SilcServer server = cmd->server;
520 char *nick = NULL, *server_name = NULL;
521 int count = 0, clients_count = 0;
522 SilcClientEntry *clients = NULL, entry;
523 SilcClientID **client_id = NULL;
524 unsigned int client_id_count = 0;
527 /* Protocol dictates that we must always send the received WHOIS request
528 to our router if we are normal server, so let's do it now unless we
529 are standalone. We will not send any replies to the client until we
530 have received reply from the router. */
531 if (server->server_type == SILC_SERVER &&
532 !cmd->pending && !server->standalone) {
534 unsigned short old_ident;
536 old_ident = silc_command_get_ident(cmd->payload);
537 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
538 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
540 /* Send WHOIS command to our router */
541 silc_server_packet_send(server, (SilcSocketConnection)
542 server->router->connection,
543 SILC_PACKET_COMMAND, cmd->packet->flags,
544 tmpbuf->data, tmpbuf->len, TRUE);
546 /* Reprocess this packet after received reply from router */
547 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
548 silc_command_get_ident(cmd->payload),
549 silc_server_command_whois, (void *)cmd);
552 silc_command_set_ident(cmd->payload, old_ident);
554 silc_buffer_free(tmpbuf);
559 /* We are ready to process the command request. Let's search for the
560 requested client and send reply to the requesting client. */
562 /* Parse the whois request */
563 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
564 &nick, &server_name, &count,
568 /* Get all clients matching that ID or nickname from local list */
569 if (client_id_count) {
570 /* Check all Client ID's received in the command packet */
571 for (i = 0; i < client_id_count; i++) {
572 entry = silc_idlist_find_client_by_id(server->local_list,
575 clients = silc_realloc(clients, sizeof(*clients) *
576 (clients_count + 1));
577 clients[clients_count++] = entry;
581 clients = silc_idlist_get_clients_by_nickname(server->local_list,
586 /* Check global list as well */
588 if (client_id_count) {
589 /* Check all Client ID's received in the command packet */
590 for (i = 0; i < client_id_count; i++) {
591 entry = silc_idlist_find_client_by_id(server->global_list,
594 clients = silc_realloc(clients, sizeof(*clients) *
595 (clients_count + 1));
596 clients[clients_count++] = entry;
600 clients = silc_idlist_get_clients_by_nickname(server->global_list,
607 /* Such client(s) really does not exist in the SILC network. */
608 if (!client_id_count) {
609 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
610 SILC_STATUS_ERR_NO_SUCH_NICK,
611 3, nick, strlen(nick));
613 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
614 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
615 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
616 2, idp->data, idp->len);
617 silc_buffer_free(idp);
622 /* Router always finds the client entry if it exists in the SILC network.
623 However, it might be incomplete entry and does not include all the
624 mandatory fields that WHOIS command reply requires. Check for these and
625 make query from the server who owns the client if some fields are
627 if (server->server_type == SILC_ROUTER &&
628 !silc_server_command_whois_check(cmd, clients, clients_count)) {
633 /* Send the command reply to the client */
634 silc_server_command_whois_send_reply(cmd, clients, clients_count);
637 if (client_id_count) {
638 for (i = 0; i < client_id_count; i++)
639 silc_free(client_id[i]);
640 silc_free(client_id);
647 silc_free(server_name);
653 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
655 SilcServer server = cmd->server;
656 char *nick = NULL, *server_name = NULL;
657 int count = 0, clients_count = 0;
658 SilcClientEntry *clients = NULL, entry;
659 SilcClientID **client_id = NULL;
660 unsigned int client_id_count = 0;
663 /* Parse the whois request */
664 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
665 &nick, &server_name, &count,
669 /* Process the command request. Let's search for the requested client and
670 send reply to the requesting server. */
672 if (client_id_count) {
673 /* Check all Client ID's received in the command packet */
674 for (i = 0; i < client_id_count; i++) {
675 entry = silc_idlist_find_client_by_id(server->local_list,
678 clients = silc_realloc(clients, sizeof(*clients) *
679 (clients_count + 1));
680 clients[clients_count++] = entry;
684 clients = silc_idlist_get_clients_by_nickname(server->local_list,
688 clients = silc_idlist_get_clients_by_hash(server->local_list,
689 nick, server->md5hash,
693 /* If we are router we will check our global list as well. */
694 if (!clients && server->server_type == SILC_ROUTER) {
695 if (client_id_count) {
696 /* Check all Client ID's received in the command packet */
697 for (i = 0; i < client_id_count; i++) {
698 entry = silc_idlist_find_client_by_id(server->global_list,
701 clients = silc_realloc(clients, sizeof(*clients) *
702 (clients_count + 1));
703 clients[clients_count++] = entry;
707 clients = silc_idlist_get_clients_by_nickname(server->global_list,
711 clients = silc_idlist_get_clients_by_hash(server->global_list,
712 nick, server->md5hash,
718 /* Such a client really does not exist in the SILC network. */
719 if (!client_id_count) {
720 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
721 SILC_STATUS_ERR_NO_SUCH_NICK,
722 3, nick, strlen(nick));
724 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
725 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
726 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
727 2, idp->data, idp->len);
728 silc_buffer_free(idp);
733 /* Router always finds the client entry if it exists in the SILC network.
734 However, it might be incomplete entry and does not include all the
735 mandatory fields that WHOIS command reply requires. Check for these and
736 make query from the server who owns the client if some fields are
738 if (server->server_type == SILC_ROUTER &&
739 !silc_server_command_whois_check(cmd, clients, clients_count)) {
744 /* Send the command reply to the client */
745 silc_server_command_whois_send_reply(cmd, clients, clients_count);
748 if (client_id_count) {
749 for (i = 0; i < client_id_count; i++)
750 silc_free(client_id[i]);
751 silc_free(client_id);
758 silc_free(server_name);
763 /* Server side of command WHOIS. Processes user's query and sends found
764 results as command replies back to the client. */
766 SILC_SERVER_CMD_FUNC(whois)
768 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
771 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3);
773 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
774 ret = silc_server_command_whois_from_client(cmd);
776 ret = silc_server_command_whois_from_server(cmd);
779 silc_server_command_free(cmd);
782 SILC_SERVER_CMD_FUNC(whowas)
786 /******************************************************************************
790 ******************************************************************************/
792 /* Checks that all mandatory fields are present. If not then send WHOIS
793 request to the server who owns the client. We use WHOIS because we want
794 to get as much information as possible at once. */
797 silc_server_command_identify_check(SilcServerCommandContext cmd,
798 SilcClientEntry *clients,
799 unsigned int clients_count)
801 SilcServer server = cmd->server;
803 SilcClientEntry entry;
805 for (i = 0; i < clients_count; i++) {
808 if (!entry->nickname) {
810 unsigned short old_ident;
815 old_ident = silc_command_get_ident(cmd->payload);
816 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
817 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
818 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
820 /* Send WHOIS request. We send WHOIS since we're doing the requesting
821 now anyway so make it a good one. */
822 silc_server_packet_send(server, entry->router->connection,
823 SILC_PACKET_COMMAND, cmd->packet->flags,
824 tmpbuf->data, tmpbuf->len, TRUE);
826 /* Reprocess this packet after received reply */
827 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
828 silc_command_get_ident(cmd->payload),
829 silc_server_command_identify, (void *)cmd);
832 /* Put old data back to the Command Payload we just changed */
833 silc_command_set_ident(cmd->payload, old_ident);
834 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
836 silc_buffer_free(tmpbuf);
845 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
846 SilcClientEntry *clients,
847 unsigned int clients_count)
849 SilcServer server = cmd->server;
851 int i, count = 0, len;
852 SilcBuffer packet, idp;
853 SilcClientEntry entry;
854 SilcCommandStatus status;
855 unsigned short ident = silc_command_get_ident(cmd->payload);
857 status = SILC_STATUS_OK;
858 if (clients_count > 1)
859 status = SILC_STATUS_LIST_START;
861 for (i = 0; i < clients_count; i++) {
864 if (count && i - 1 == count)
867 if (clients_count > 2)
868 status = SILC_STATUS_LIST_ITEM;
870 if (clients_count > 1 && i == clients_count - 1)
871 status = SILC_STATUS_LIST_END;
873 /* Send IDENTIFY reply */
874 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
875 tmp = silc_argument_get_first_arg(cmd->args, NULL);
879 char nh[256], uh[256];
880 SilcSocketConnection hsock;
882 memset(uh, 0, sizeof(uh));
883 memset(nh, 0, sizeof(nh));
885 strncat(nh, entry->nickname, strlen(entry->nickname));
886 if (!strchr(entry->nickname, '@')) {
888 len = entry->router ? strlen(entry->router->server_name) :
889 strlen(server->server_name);
890 strncat(nh, entry->router ? entry->router->server_name :
891 server->server_name, len);
894 if (!entry->username) {
895 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
896 SILC_STATUS_OK, ident, 2,
897 2, idp->data, idp->len,
900 strncat(uh, entry->username, strlen(entry->username));
901 if (!strchr(entry->username, '@')) {
903 hsock = (SilcSocketConnection)entry->connection;
904 len = strlen(hsock->hostname);
905 strncat(uh, hsock->hostname, len);
908 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
909 SILC_STATUS_OK, ident, 3,
910 2, idp->data, idp->len,
915 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
916 0, packet->data, packet->len, FALSE);
918 silc_buffer_free(packet);
919 silc_buffer_free(idp);
925 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
927 SilcServer server = cmd->server;
928 char *nick = NULL, *server_name = NULL;
929 int count = 0, clients_count = 0;
930 SilcClientEntry *clients = NULL, entry;
931 SilcClientID **client_id = NULL;
932 unsigned int client_id_count = 0;
935 /* Protocol dictates that we must always send the received IDENTIFY request
936 to our router if we are normal server, so let's do it now unless we
937 are standalone. We will not send any replies to the client until we
938 have received reply from the router. */
939 if (server->server_type == SILC_SERVER &&
940 !cmd->pending && !server->standalone) {
942 unsigned short old_ident;
944 old_ident = silc_command_get_ident(cmd->payload);
945 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
946 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
948 /* Send IDENTIFY command to our router */
949 silc_server_packet_send(server, (SilcSocketConnection)
950 server->router->connection,
951 SILC_PACKET_COMMAND, cmd->packet->flags,
952 tmpbuf->data, tmpbuf->len, TRUE);
954 /* Reprocess this packet after received reply from router */
955 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
956 silc_command_get_ident(cmd->payload),
957 silc_server_command_identify, (void *)cmd);
960 silc_command_set_ident(cmd->payload, old_ident);
962 silc_buffer_free(tmpbuf);
967 /* We are ready to process the command request. Let's search for the
968 requested client and send reply to the requesting client. */
970 /* Parse the IDENTIFY request */
971 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
972 &nick, &server_name, &count,
973 SILC_COMMAND_IDENTIFY))
976 /* Get all clients matching that ID or nickname from local list */
977 if (client_id_count) {
978 /* Check all Client ID's received in the command packet */
979 for (i = 0; i < client_id_count; i++) {
980 entry = silc_idlist_find_client_by_id(server->local_list,
983 clients = silc_realloc(clients, sizeof(*clients) *
984 (clients_count + 1));
985 clients[clients_count++] = entry;
989 clients = silc_idlist_get_clients_by_nickname(server->local_list,
994 /* Check global list as well */
996 if (client_id_count) {
997 /* Check all Client ID's received in the command packet */
998 for (i = 0; i < client_id_count; i++) {
999 entry = silc_idlist_find_client_by_id(server->global_list,
1000 client_id[i], NULL);
1002 clients = silc_realloc(clients, sizeof(*clients) *
1003 (clients_count + 1));
1004 clients[clients_count++] = entry;
1008 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1015 /* Such a client really does not exist in the SILC network. */
1016 if (!client_id_count) {
1017 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1018 SILC_STATUS_ERR_NO_SUCH_NICK,
1019 3, nick, strlen(nick));
1021 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1022 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1023 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1024 2, idp->data, idp->len);
1025 silc_buffer_free(idp);
1030 /* Check that all mandatory fields are present and request those data
1031 from the server who owns the client if necessary. */
1032 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1033 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1038 /* Send the command reply to the client */
1039 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1042 if (client_id_count) {
1043 for (i = 0; i < client_id_count; i++)
1044 silc_free(client_id[i]);
1045 silc_free(client_id);
1052 silc_free(server_name);
1058 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1060 SilcServer server = cmd->server;
1061 char *nick = NULL, *server_name = NULL;
1062 int count = 0, clients_count = 0;
1063 SilcClientEntry *clients = NULL, entry;
1064 SilcClientID **client_id = NULL;
1065 unsigned int client_id_count = 0;
1068 /* Parse the IDENTIFY request */
1069 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1070 &nick, &server_name, &count,
1071 SILC_COMMAND_IDENTIFY))
1074 /* Process the command request. Let's search for the requested client and
1075 send reply to the requesting server. */
1077 if (client_id_count) {
1078 /* Check all Client ID's received in the command packet */
1079 for (i = 0; i < client_id_count; i++) {
1080 entry = silc_idlist_find_client_by_id(server->local_list,
1081 client_id[i], NULL);
1083 clients = silc_realloc(clients, sizeof(*clients) *
1084 (clients_count + 1));
1085 clients[clients_count++] = entry;
1089 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1093 clients = silc_idlist_get_clients_by_hash(server->local_list,
1094 nick, server->md5hash,
1098 /* If we are router we will check our global list as well. */
1099 if (!clients && server->server_type == SILC_ROUTER) {
1100 if (client_id_count) {
1101 /* Check all Client ID's received in the command packet */
1102 for (i = 0; i < client_id_count; i++) {
1103 entry = silc_idlist_find_client_by_id(server->global_list,
1104 client_id[i], NULL);
1106 clients = silc_realloc(clients, sizeof(*clients) *
1107 (clients_count + 1));
1108 clients[clients_count++] = entry;
1112 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1116 clients = silc_idlist_get_clients_by_hash(server->global_list,
1117 nick, server->md5hash,
1123 /* Such a client really does not exist in the SILC network. */
1124 if (!client_id_count) {
1125 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1126 SILC_STATUS_ERR_NO_SUCH_NICK,
1127 3, nick, strlen(nick));
1129 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1130 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1131 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1132 2, idp->data, idp->len);
1133 silc_buffer_free(idp);
1138 /* Check that all mandatory fields are present and request those data
1139 from the server who owns the client if necessary. */
1140 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1141 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1146 /* Send the command reply */
1147 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1150 if (client_id_count) {
1151 for (i = 0; i < client_id_count; i++)
1152 silc_free(client_id[i]);
1153 silc_free(client_id);
1160 silc_free(server_name);
1165 SILC_SERVER_CMD_FUNC(identify)
1167 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1170 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3);
1172 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1173 ret = silc_server_command_identify_from_client(cmd);
1175 ret = silc_server_command_identify_from_server(cmd);
1178 silc_server_command_free(cmd);
1181 /* Checks string for bad characters and returns TRUE if they are found. */
1183 static int silc_server_command_bad_chars(char *nick)
1185 if (strchr(nick, '\\')) return TRUE;
1186 if (strchr(nick, '\"')) return TRUE;
1187 if (strchr(nick, '´')) return TRUE;
1188 if (strchr(nick, '`')) return TRUE;
1189 if (strchr(nick, '\'')) return TRUE;
1190 if (strchr(nick, '*')) return TRUE;
1191 if (strchr(nick, '/')) return TRUE;
1192 if (strchr(nick, '@')) return TRUE;
1197 /* Server side of command NICK. Sets nickname for user. Setting
1198 nickname causes generation of a new client ID for the client. The
1199 new client ID is sent to the client after changing the nickname. */
1201 SILC_SERVER_CMD_FUNC(nick)
1203 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1204 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1205 SilcServer server = cmd->server;
1206 SilcBuffer packet, nidp, oidp;
1207 SilcClientID *new_id;
1210 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1212 /* Check nickname */
1213 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1214 if (silc_server_command_bad_chars(nick) == TRUE) {
1215 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1216 SILC_STATUS_ERR_BAD_NICKNAME);
1220 /* Create new Client ID */
1221 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1222 cmd->server->md5hash, nick,
1225 /* Send notify about nickname change to our router. We send the new
1226 ID and ask to replace it with the old one. If we are router the
1227 packet is broadcasted. */
1228 if (!cmd->server->standalone)
1229 silc_server_send_replace_id(server, server->router->connection,
1230 server->server_type == SILC_SERVER ?
1231 FALSE : TRUE, client->id,
1232 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1233 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1235 /* Remove old cache entry */
1236 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1239 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1243 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1244 silc_free(client->id);
1247 /* Save the nickname as this client is our local client */
1248 if (client->nickname)
1249 silc_free(client->nickname);
1251 client->nickname = strdup(nick);
1252 client->id = new_id;
1254 /* Update client cache */
1255 silc_idcache_add(server->local_list->clients, client->nickname,
1256 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1258 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1260 /* Send NICK_CHANGE notify */
1261 silc_server_send_notify_on_channels(server, client,
1262 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1263 oidp->data, oidp->len,
1264 nidp->data, nidp->len);
1266 /* Send the new Client ID as reply command back to client */
1267 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1268 SILC_STATUS_OK, 0, 1,
1269 2, nidp->data, nidp->len);
1270 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1271 0, packet->data, packet->len, FALSE);
1273 silc_buffer_free(packet);
1274 silc_buffer_free(nidp);
1275 silc_buffer_free(oidp);
1278 silc_server_command_free(cmd);
1281 SILC_SERVER_CMD_FUNC(list)
1285 /* Server side of TOPIC command. Sets topic for channel and/or returns
1286 current topic to client. */
1288 SILC_SERVER_CMD_FUNC(topic)
1290 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1291 SilcServer server = cmd->server;
1292 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1293 SilcChannelID *channel_id;
1294 SilcChannelEntry channel;
1295 SilcChannelClientEntry chl;
1296 SilcBuffer packet, idp;
1298 unsigned int argc, tmp_len;
1300 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1302 argc = silc_argument_get_arg_num(cmd->args);
1304 /* Get Channel ID */
1305 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1308 SILC_STATUS_ERR_NO_CHANNEL_ID);
1311 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1313 /* Check whether the channel exists */
1314 channel = silc_idlist_find_channel_by_id(server->local_list,
1317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1318 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1324 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1327 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1331 if (strlen(tmp) > 256) {
1332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1333 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1337 /* See whether has rights to change topic */
1338 silc_list_start(channel->user_list);
1339 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1340 if (chl->client == client) {
1341 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1343 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1351 /* Set the topic for channel */
1353 silc_free(channel->topic);
1354 channel->topic = strdup(tmp);
1356 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1358 /* Send notify about topic change to all clients on the channel */
1359 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1360 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1361 idp->data, idp->len,
1362 channel->topic, strlen(channel->topic));
1363 silc_buffer_free(idp);
1366 /* Send the topic to client as reply packet */
1367 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1369 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1370 SILC_STATUS_OK, 0, 2,
1371 2, idp->data, idp->len,
1373 strlen(channel->topic));
1375 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1376 SILC_STATUS_OK, 0, 1,
1377 2, idp->data, idp->len);
1378 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1379 0, packet->data, packet->len, FALSE);
1381 silc_buffer_free(packet);
1382 silc_buffer_free(idp);
1383 silc_free(channel_id);
1386 silc_server_command_free(cmd);
1389 /* Server side of INVITE command. Invites some client to join some channel. */
1391 SILC_SERVER_CMD_FUNC(invite)
1393 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1394 SilcServer server = cmd->server;
1395 SilcSocketConnection sock = cmd->sock, dest_sock;
1396 SilcClientEntry sender, dest;
1397 SilcClientID *dest_id;
1398 SilcChannelEntry channel;
1399 SilcChannelID *channel_id;
1404 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1406 /* Get destination ID */
1407 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1410 SILC_STATUS_ERR_NO_CLIENT_ID);
1413 dest_id = silc_id_payload_parse_id(tmp, len);
1415 /* Get Channel ID */
1416 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1418 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1419 SILC_STATUS_ERR_NO_CHANNEL_ID);
1422 channel_id = silc_id_payload_parse_id(tmp, len);
1424 /* Check whether the channel exists */
1425 channel = silc_idlist_find_channel_by_id(server->local_list,
1428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1429 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1433 /* Check whether the sender of this command is on the channel. */
1434 sender = (SilcClientEntry)sock->user_data;
1435 if (!silc_server_client_on_channel(sender, channel)) {
1436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1437 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1441 /* Check whether the channel is invite-only channel. If yes then the
1442 sender of this command must be at least channel operator. */
1443 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1444 SilcChannelClientEntry chl;
1446 silc_list_start(channel->user_list);
1447 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1448 if (chl->client == sender) {
1449 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1451 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1458 /* Find the connection data for the destination. If it is local we will
1459 send it directly otherwise we will send it to router for routing. */
1460 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1462 dest_sock = (SilcSocketConnection)dest->connection;
1464 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1466 /* Check whether the requested client is already on the channel. */
1467 /* XXX if we are normal server we don't know about global clients on
1468 the channel thus we must request it (USERS command), check from
1469 local cache as well. */
1470 if (silc_server_client_on_channel(dest, channel)) {
1471 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1472 SILC_STATUS_ERR_USER_ON_CHANNEL);
1476 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1478 /* Send notify to the client that is invited to the channel */
1479 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1480 SILC_NOTIFY_TYPE_INVITE, 2,
1481 sidp->data, sidp->len, tmp, len);
1483 /* Send command reply */
1484 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1487 silc_buffer_free(sidp);
1490 silc_server_command_free(cmd);
1493 /* Quits connection to client. This gets called if client won't
1494 close the connection even when it has issued QUIT command. */
1496 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1498 SilcServer server = (SilcServer)context;
1499 SilcSocketConnection sock = server->sockets[fd];
1501 /* Free all client specific data, such as client entry and entires
1502 on channels this client may be on. */
1503 silc_server_free_sock_user_data(server, sock);
1505 /* Close the connection on our side */
1506 silc_server_close_connection(server, sock);
1509 /* Quits SILC session. This is the normal way to disconnect client. */
1511 SILC_SERVER_CMD_FUNC(quit)
1513 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1514 SilcServer server = cmd->server;
1515 SilcSocketConnection sock = cmd->sock;
1517 SILC_LOG_DEBUG(("Start"));
1519 /* We quit the connection with little timeout */
1520 silc_task_register(server->timeout_queue, sock->sock,
1521 silc_server_command_quit_cb, server,
1522 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1524 silc_server_command_free(cmd);
1527 SILC_SERVER_CMD_FUNC(kill)
1531 /* Server side of command INFO. This sends information about us to
1532 the client. If client requested specific server we will send the
1533 command to that server. */
1535 SILC_SERVER_CMD_FUNC(info)
1537 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1538 SilcServer server = cmd->server;
1539 SilcBuffer packet, idp;
1540 char info_string[256], *dest_server;
1542 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1544 /* Get server name */
1545 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1547 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1548 SILC_STATUS_ERR_NO_SUCH_SERVER);
1552 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1553 /* Send our reply */
1554 memset(info_string, 0, sizeof(info_string));
1555 snprintf(info_string, sizeof(info_string),
1556 "location: %s server: %s admin: %s <%s>",
1557 server->config->admin_info->location,
1558 server->config->admin_info->server_type,
1559 server->config->admin_info->admin_name,
1560 server->config->admin_info->admin_email);
1562 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1564 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1565 SILC_STATUS_OK, 0, 2,
1566 2, idp->data, idp->len,
1568 strlen(info_string));
1569 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1570 packet->data, packet->len, FALSE);
1572 silc_buffer_free(packet);
1573 silc_buffer_free(idp);
1575 /* Send this command to the requested server */
1577 if (server->server_type == SILC_SERVER && !server->standalone) {
1581 if (server->server_type == SILC_ROUTER) {
1587 silc_server_command_free(cmd);
1590 SILC_SERVER_CMD_FUNC(connect)
1594 /* Server side of command PING. This just replies to the ping. */
1596 SILC_SERVER_CMD_FUNC(ping)
1598 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1599 SilcServer server = cmd->server;
1604 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1607 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1609 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1610 SILC_STATUS_ERR_NO_SERVER_ID);
1613 id = silc_id_str2id(tmp, SILC_ID_SERVER);
1617 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1618 /* Send our reply */
1619 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1622 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1623 SILC_STATUS_ERR_NO_SUCH_SERVER);
1630 silc_server_command_free(cmd);
1633 SILC_SERVER_CMD_FUNC(oper)
1637 /* Assembles USERS command and executes it. This is called when client
1638 joins to a channel and we wan't to send USERS command reply to the
1641 void silc_server_command_send_users(SilcServer server,
1642 SilcSocketConnection sock,
1643 SilcChannelEntry channel,
1646 SilcServerCommandContext cmd;
1647 SilcBuffer buffer, idp;
1648 SilcPacketContext *packet = silc_packet_context_alloc();
1650 /* Create USERS command packet and process it. */
1651 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1652 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1653 1, idp->data, idp->len);
1655 packet->buffer = silc_buffer_copy(buffer);
1656 packet->sock = sock;
1657 packet->type = SILC_PACKET_COMMAND;
1659 cmd = silc_calloc(1, sizeof(*cmd));
1660 cmd->payload = silc_command_payload_parse(buffer);
1661 cmd->args = silc_command_get_args(cmd->payload);
1662 cmd->server = server;
1664 cmd->packet = silc_packet_context_dup(packet);
1665 cmd->pending = FALSE;
1668 /* If this function was called from pending command then instead of
1669 processing the command now, register a pending command callback which
1670 will process it after we've received the automatic USERS command
1672 silc_server_command_pending(server, SILC_COMMAND_USERS, 0,
1673 silc_server_command_users, (void *)cmd);
1674 cmd->pending = TRUE;
1680 /* Process USERS command. */
1681 silc_server_command_users((void *)cmd);
1685 silc_packet_context_free(packet);
1688 /* Internal routine to join channel. The channel sent to this function
1689 has been either created or resolved from ID lists. This joins the sent
1690 client to the channel. */
1692 static void silc_server_command_join_channel(SilcServer server,
1693 SilcServerCommandContext cmd,
1694 SilcChannelEntry channel,
1695 SilcClientID *client_id,
1699 SilcSocketConnection sock = cmd->sock;
1701 unsigned int tmp_len;
1702 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1703 SilcClientEntry client;
1704 SilcChannelClientEntry chl;
1705 SilcBuffer reply, chidp, clidp, keyp;
1706 unsigned short ident = silc_command_get_ident(cmd->payload);
1708 SILC_LOG_DEBUG(("Start"));
1713 /* Get passphrase */
1714 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1716 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1717 memcpy(passphrase, tmp, tmp_len);
1721 * Check channel modes
1724 /* Check invite list if channel is invite-only channel */
1725 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1726 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1727 /* Invite list is specified. Check whether client is invited in the
1728 list. If not, then check whether it has been invited otherwise. */
1731 /* XXX client must be invited to be able to join the channel */
1735 /* Check ban list if set */
1736 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1740 /* Check the channel passphrase if set. */
1741 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1742 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1743 strlen(channel->mode_data.passphrase))) {
1744 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1745 SILC_STATUS_ERR_BAD_PASSWORD);
1750 /* Check user count limit if set. */
1751 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1752 if (silc_list_count(channel->user_list) + 1 >
1753 channel->mode_data.user_limit) {
1754 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1755 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1761 * Client is allowed to join to the channel. Make it happen.
1764 /* Get the client entry */
1765 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1766 client = (SilcClientEntry)sock->user_data;
1768 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1771 /* XXX actually this is useless since router finds always cell's
1772 local clients from its local lists. */
1773 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1780 /* Check whether the client already is on the channel */
1781 if (silc_server_client_on_channel(client, channel)) {
1782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1783 SILC_STATUS_ERR_USER_ON_CHANNEL);
1787 /* Generate new channel key as protocol dictates */
1788 if (!created || !channel->channel_key)
1789 silc_server_create_channel_key(server, channel, 0);
1791 /* Send the channel key. This is broadcasted to the channel but is not
1792 sent to the client who is joining to the channel. */
1793 silc_server_send_channel_key(server, NULL, channel,
1794 server->server_type == SILC_ROUTER ?
1795 FALSE : server->standalone);
1797 /* Join the client to the channel by adding it to channel's user list.
1798 Add also the channel to client entry's channels list for fast cross-
1800 chl = silc_calloc(1, sizeof(*chl));
1802 chl->client = client;
1803 chl->channel = channel;
1804 silc_list_add(channel->user_list, chl);
1805 silc_list_add(client->channels, chl);
1807 /* Encode Client ID Payload of the original client who wants to join */
1808 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1810 /* Encode command reply packet */
1811 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1812 SILC_PUT32_MSB(channel->mode, mode);
1813 SILC_PUT32_MSB(created, tmp2);
1814 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1815 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1816 SILC_ID_CHANNEL_LEN,
1817 channel->channel_key->cipher->name,
1818 channel->key_len / 8, channel->key);
1820 if (!channel->topic) {
1822 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1823 SILC_STATUS_OK, ident, 5,
1824 2, channel->channel_name,
1825 strlen(channel->channel_name),
1826 3, chidp->data, chidp->len,
1829 6, keyp->data, keyp->len);
1832 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1833 SILC_STATUS_OK, ident, 6,
1834 2, channel->channel_name,
1835 strlen(channel->channel_name),
1836 3, chidp->data, chidp->len,
1839 6, keyp->data, keyp->len,
1841 strlen(channel->topic));
1844 /* Send command reply */
1845 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1846 reply->data, reply->len, FALSE);
1848 if (!cmd->pending) {
1849 /* Send JOIN notify to locally connected clients on the channel */
1850 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1851 SILC_NOTIFY_TYPE_JOIN, 1,
1852 clidp->data, clidp->len);
1854 /* Send NEW_CHANNEL_USER packet to our primary router */
1855 if (!server->standalone)
1856 silc_server_send_new_channel_user(server, server->router->connection,
1857 server->server_type == SILC_SERVER ?
1859 channel->id, SILC_ID_CHANNEL_LEN,
1860 client->id, SILC_ID_CLIENT_LEN);
1863 /* Send USERS command reply to the joined channel so the user sees who
1864 is currently on the channel. */
1865 silc_server_command_send_users(server, sock, channel, cmd->pending);
1867 silc_buffer_free(reply);
1868 silc_buffer_free(clidp);
1869 silc_buffer_free(chidp);
1870 silc_buffer_free(keyp);
1874 silc_free(passphrase);
1877 /* Server side of command JOIN. Joins client into requested channel. If
1878 the channel does not exist it will be created. */
1880 SILC_SERVER_CMD_FUNC(join)
1882 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1883 SilcServer server = cmd->server;
1885 char *tmp, *channel_name = NULL, *cipher = NULL;
1886 SilcChannelEntry channel;
1887 unsigned int umode = 0;
1888 int created = FALSE;
1889 SilcClientID *client_id;
1891 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1893 /* Get channel name */
1894 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1897 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1902 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1904 SILC_STATUS_ERR_BAD_CHANNEL);
1905 silc_free(channel_name);
1909 /* Get Client ID of the client who is joining to the channel */
1910 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1912 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1913 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1916 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1920 /* Get cipher name */
1921 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
1923 /* See if the channel exists */
1924 channel = silc_idlist_find_channel_by_name(server->local_list,
1925 channel_name, NULL);
1927 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1928 /* If this is coming from client the Client ID in the command packet must
1929 be same as the client's ID. */
1930 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1931 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
1932 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
1933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1934 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1940 /* Channel not found */
1942 /* If we are standalone server we don't have a router, we just create
1943 the channel by ourselves. */
1944 if (server->standalone) {
1945 channel = silc_server_create_new_channel(server, server->id, cipher,
1947 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1952 /* The channel does not exist on our server. If we are normal server
1953 we will send JOIN command to our router which will handle the
1954 joining procedure (either creates the channel if it doesn't exist
1955 or joins the client to it). */
1956 if (server->server_type == SILC_SERVER) {
1958 unsigned short old_ident;
1960 old_ident = silc_command_get_ident(cmd->payload);
1961 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1962 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1964 /* Send JOIN command to our router */
1965 silc_server_packet_send(server, (SilcSocketConnection)
1966 server->router->connection,
1967 SILC_PACKET_COMMAND, cmd->packet->flags,
1968 tmpbuf->data, tmpbuf->len, TRUE);
1970 /* Reprocess this packet after received reply from router */
1971 silc_server_command_pending(server, SILC_COMMAND_JOIN,
1972 silc_command_get_ident(cmd->payload),
1973 silc_server_command_join, context);
1974 cmd->pending = TRUE;
1978 /* We are router and the channel does not seem exist so we will check
1979 our global list as well for the channel. */
1980 channel = silc_idlist_find_channel_by_name(server->global_list,
1981 channel_name, NULL);
1983 /* Channel really does not exist, create it */
1984 channel = silc_server_create_new_channel(server, server->id, cipher,
1986 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1993 /* Channel not found */
1995 /* If the command came from router and/or we are normal server then
1996 something went wrong with the joining as the channel was not found.
1997 We can't do anything else but ignore this. */
1998 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
1999 server->server_type == SILC_SERVER)
2002 /* We are router and the channel does not seem exist so we will check
2003 our global list as well for the channel. */
2004 channel = silc_idlist_find_channel_by_name(server->global_list,
2005 channel_name, NULL);
2007 /* Channel really does not exist, create it */
2008 channel = silc_server_create_new_channel(server, server->id, cipher,
2010 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2016 /* If the channel does not have global users and is also empty it means the
2017 channel was created globally (by our router) and the client will be the
2018 channel founder and operator. */
2019 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2020 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2021 created = TRUE; /* Created globally by our router */
2024 /* Join to the channel */
2025 silc_server_command_join_channel(server, cmd, channel, client_id,
2028 silc_free(client_id);
2031 silc_server_command_free(cmd);
2034 /* Server side of command MOTD. Sends server's current "message of the
2035 day" to the client. */
2037 SILC_SERVER_CMD_FUNC(motd)
2039 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2040 SilcServer server = cmd->server;
2044 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2046 /* XXX show currently only our motd */
2048 if (server->config && server->config->motd &&
2049 server->config->motd->motd_file) {
2052 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2057 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2063 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2068 silc_server_command_free(cmd);
2071 SILC_SERVER_CMD_FUNC(umode)
2075 /* Checks that client has rights to add or remove channel modes. If any
2076 of the checks fails FALSE is returned. */
2078 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2079 SilcChannelClientEntry client,
2082 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2083 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2085 /* Check whether has rights to change anything */
2086 if (!is_op && !is_fo)
2089 /* Check whether has rights to change everything */
2093 /* We know that client is channel operator, check that they are not
2094 changing anything that requires channel founder rights. Rest of the
2095 modes are available automatically for channel operator. */
2097 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2098 if (is_op && !is_fo)
2101 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2102 if (is_op && !is_fo)
2107 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2108 if (is_op && !is_fo)
2111 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2112 if (is_op && !is_fo)
2117 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2118 if (is_op && !is_fo)
2121 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2122 if (is_op && !is_fo)
2130 /* Server side command of CMODE. Changes channel mode */
2132 SILC_SERVER_CMD_FUNC(cmode)
2134 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2135 SilcServer server = cmd->server;
2136 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2137 SilcChannelID *channel_id;
2138 SilcChannelEntry channel;
2139 SilcChannelClientEntry chl;
2140 SilcBuffer packet, cidp;
2141 unsigned char *tmp, *tmp_id, *tmp_mask;
2142 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2144 SILC_LOG_DEBUG(("Start"));
2146 argc = silc_argument_get_arg_num(cmd->args);
2148 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2149 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2153 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2154 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2158 /* Get Channel ID */
2159 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2161 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2162 SILC_STATUS_ERR_NO_CHANNEL_ID);
2165 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2167 /* Get the channel mode mask */
2168 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2170 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2171 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2174 SILC_GET32_MSB(mode_mask, tmp_mask);
2176 /* Get channel entry */
2177 channel = silc_idlist_find_channel_by_id(server->local_list,
2180 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2181 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2185 /* Check whether this client is on the channel */
2186 if (!silc_server_client_on_channel(client, channel)) {
2187 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2188 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2192 /* Get entry to the channel user list */
2193 silc_list_start(channel->user_list);
2194 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2195 if (chl->client == client)
2198 /* Check that client has rights to change any requested channel modes */
2199 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2200 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2201 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2206 * Check the modes. Modes that requires nothing special operation are
2210 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2211 /* Channel uses private keys to protect traffic. Client(s) has set the
2212 key locally they want to use, server does not know that key. */
2213 /* Nothing interesting to do here now */
2215 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2216 /* The mode is removed and we need to generate and distribute
2217 new channel key. Clients are not using private channel keys
2218 anymore after this. */
2220 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2223 /* Re-generate channel key */
2224 silc_server_create_channel_key(server, channel, 0);
2226 /* Encode channel key payload to be distributed on the channel */
2228 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2229 strlen(channel->channel_key->
2231 channel->channel_key->cipher->name,
2232 channel->key_len / 8, channel->key);
2234 /* If we are normal server then we will send it to our router. If we
2235 are router we will send it to all local servers that has clients on
2237 if (server->server_type == SILC_SERVER) {
2238 if (!server->standalone)
2239 silc_server_packet_send(server,
2240 cmd->server->router->connection,
2241 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2247 /* Send to locally connected clients on the channel */
2248 silc_server_packet_send_local_channel(server, channel,
2249 SILC_PACKET_CHANNEL_KEY, 0,
2250 packet->data, packet->len, FALSE);
2251 silc_buffer_free(packet);
2255 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2256 /* User limit is set on channel */
2257 unsigned int user_limit;
2259 /* Get user limit */
2260 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2262 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2263 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2264 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2268 SILC_GET32_MSB(user_limit, tmp);
2269 channel->mode_data.user_limit = user_limit;
2272 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2273 /* User limit mode is unset. Remove user limit */
2274 channel->mode_data.user_limit = 0;
2277 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2278 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2279 /* Passphrase has been set to channel */
2281 /* Get the passphrase */
2282 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2285 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2289 /* Save the passphrase */
2290 channel->mode_data.passphrase = strdup(tmp);
2293 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2294 /* Passphrase mode is unset. remove the passphrase */
2295 if (channel->mode_data.passphrase) {
2296 silc_free(channel->mode_data.passphrase);
2297 channel->mode_data.passphrase = NULL;
2302 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2303 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2304 /* Ban list is specified for channel */
2307 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2310 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2314 /* XXX check that channel founder is not banned */
2316 /* Save the ban list */
2317 channel->mode_data.ban_list = strdup(tmp);
2320 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2321 /* Ban mode is unset. Remove the entire ban list */
2322 if (channel->mode_data.ban_list) {
2323 silc_free(channel->mode_data.ban_list);
2324 channel->mode_data.ban_list = NULL;
2329 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2330 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2331 /* Invite list is specified for channel */
2333 /* Get invite list */
2334 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2337 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2341 /* Save the invite linst */
2342 channel->mode_data.invite_list = strdup(tmp);
2345 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2346 /* Invite list mode is unset. Remove the entire invite list */
2347 if (channel->mode_data.invite_list) {
2348 silc_free(channel->mode_data.invite_list);
2349 channel->mode_data.invite_list = NULL;
2354 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2355 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2356 /* Cipher to use protect the traffic */
2357 unsigned int key_len = 128;
2361 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2363 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2364 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2368 cp = strchr(tmp, ':');
2374 /* XXX Duplicated code, make own function for this!! */
2376 /* Delete old cipher and allocate the new one */
2377 silc_cipher_free(channel->channel_key);
2378 silc_cipher_alloc(tmp, &channel->channel_key);
2384 /* Re-generate channel key */
2385 silc_server_create_channel_key(server, channel, key_len);
2387 /* Encode channel key payload to be distributed on the channel */
2389 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2390 strlen(channel->channel_key->
2392 channel->channel_key->cipher->name,
2393 channel->key_len / 8, channel->key);
2395 /* If we are normal server then we will send it to our router. If we
2396 are router we will send it to all local servers that has clients on
2398 if (server->server_type == SILC_SERVER) {
2399 if (!server->standalone)
2400 silc_server_packet_send(server,
2401 cmd->server->router->connection,
2402 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2408 /* Send to locally connected clients on the channel */
2409 silc_server_packet_send_local_channel(server, channel,
2410 SILC_PACKET_CHANNEL_KEY, 0,
2411 packet->data, packet->len, FALSE);
2412 silc_buffer_free(packet);
2415 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2416 /* Cipher mode is unset. Remove the cipher and revert back to
2419 if (channel->mode_data.cipher) {
2420 silc_free(channel->mode_data.cipher);
2421 channel->mode_data.cipher = NULL;
2422 channel->mode_data.key_len = 0;
2425 /* Generate new cipher and key for the channel */
2427 /* XXX Duplicated code, make own function for this!! */
2429 /* Delete old cipher and allocate default one */
2430 silc_cipher_free(channel->channel_key);
2431 if (!channel->cipher)
2432 silc_cipher_alloc("twofish", &channel->channel_key);
2434 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2436 /* Re-generate channel key */
2437 silc_server_create_channel_key(server, channel, 0);
2439 /* Encode channel key payload to be distributed on the channel */
2441 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2442 strlen(channel->channel_key->
2444 channel->channel_key->cipher->name,
2445 channel->key_len / 8, channel->key);
2447 /* If we are normal server then we will send it to our router. If we
2448 are router we will send it to all local servers that has clients on
2450 if (server->server_type == SILC_SERVER) {
2451 if (!server->standalone)
2452 silc_server_packet_send(server,
2453 cmd->server->router->connection,
2454 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2460 /* Send to locally connected clients on the channel */
2461 silc_server_packet_send_local_channel(server, channel,
2462 SILC_PACKET_CHANNEL_KEY, 0,
2463 packet->data, packet->len, FALSE);
2464 silc_buffer_free(packet);
2468 /* Finally, set the mode */
2469 channel->mode = mode_mask;
2471 /* Send CMODE_CHANGE notify */
2472 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2473 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2474 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2475 cidp->data, cidp->len,
2479 /* Send command reply to sender */
2480 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2481 SILC_STATUS_OK, 0, 1,
2483 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2484 packet->data, packet->len, FALSE);
2486 silc_buffer_free(packet);
2487 silc_free(channel_id);
2490 silc_server_command_free(cmd);
2493 /* Server side of CUMODE command. Changes client's mode on a channel. */
2495 SILC_SERVER_CMD_FUNC(cumode)
2497 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2498 SilcServer server = cmd->server;
2499 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2500 SilcChannelID *channel_id;
2501 SilcClientID *client_id;
2502 SilcChannelEntry channel;
2503 SilcClientEntry target_client;
2504 SilcChannelClientEntry chl;
2505 SilcBuffer packet, idp;
2506 unsigned char *tmp_id, *tmp_mask;
2507 unsigned int target_mask, sender_mask, tmp_len;
2510 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2512 /* Get Channel ID */
2513 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2515 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2516 SILC_STATUS_ERR_NO_CHANNEL_ID);
2519 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2521 /* Get channel entry */
2522 channel = silc_idlist_find_channel_by_id(server->local_list,
2525 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2526 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2530 /* Check whether sender is on the channel */
2531 if (!silc_server_client_on_channel(client, channel)) {
2532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2533 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2537 /* Check that client has rights to change other's rights */
2538 silc_list_start(channel->user_list);
2539 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2540 if (chl->client == client) {
2541 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2542 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2543 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2544 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2548 sender_mask = chl->mode;
2553 /* Get the target client's channel mode mask */
2554 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2556 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2557 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2560 SILC_GET32_MSB(target_mask, tmp_mask);
2562 /* Get target Client ID */
2563 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2565 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2566 SILC_STATUS_ERR_NO_CHANNEL_ID);
2569 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2571 /* Get target client's entry */
2572 target_client = silc_idlist_find_client_by_id(server->local_list,
2574 if (!target_client) {
2575 /* XXX If target client is not one of mine send to primary route */
2578 /* Check whether target client is on the channel */
2579 if (!silc_server_client_on_channel(target_client, channel)) {
2580 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2581 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2585 /* Get entry to the channel user list */
2586 silc_list_start(channel->user_list);
2587 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2588 if (chl->client == target_client)
2595 /* If the target client is founder, no one else can change their mode
2597 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2598 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2599 SILC_STATUS_ERR_NOT_YOU);
2603 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2604 /* Cannot promote anyone to channel founder */
2605 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2606 SILC_STATUS_ERR_NOT_YOU);
2609 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2610 if (target_client == client) {
2611 /* Remove channel founder rights from itself */
2612 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2616 SILC_STATUS_ERR_NOT_YOU);
2622 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2623 /* Promote to operator */
2624 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2625 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2629 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2630 /* Demote to normal user */
2631 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2636 /* Send notify to channel, notify only if mode was actually changed. */
2638 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2639 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2640 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2641 idp->data, idp->len,
2642 tmp_mask, 4, tmp_id, tmp_len);
2643 silc_buffer_free(idp);
2646 /* Send command reply to sender */
2647 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2648 SILC_STATUS_OK, 0, 2,
2650 3, tmp_id, tmp_len);
2651 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2652 packet->data, packet->len, FALSE);
2654 silc_buffer_free(packet);
2655 silc_free(channel_id);
2656 silc_free(client_id);
2659 silc_server_command_free(cmd);
2662 /* Server side of KICK command. Kicks client out of channel. */
2664 SILC_SERVER_CMD_FUNC(kick)
2668 SILC_SERVER_CMD_FUNC(restart)
2672 SILC_SERVER_CMD_FUNC(close)
2676 SILC_SERVER_CMD_FUNC(die)
2680 SILC_SERVER_CMD_FUNC(silcoper)
2684 /* Server side command of LEAVE. Removes client from a channel. */
2686 SILC_SERVER_CMD_FUNC(leave)
2688 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2689 SilcServer server = cmd->server;
2690 SilcSocketConnection sock = cmd->sock;
2691 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2693 SilcChannelEntry channel;
2695 unsigned int i, len;
2698 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2700 /* Get Channel ID */
2701 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2704 SILC_STATUS_ERR_NO_CHANNEL_ID);
2707 id = silc_id_payload_parse_id(tmp, len);
2709 /* Get channel entry */
2710 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2712 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2713 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2717 /* Check whether this client is on the channel */
2718 if (!silc_server_client_on_channel(id_entry, channel)) {
2719 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2720 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2724 /* Notify routers that they should remove this client from their list
2725 of clients on the channel. */
2726 if (!server->standalone)
2727 silc_server_send_remove_channel_user(server,
2728 server->router->connection,
2729 server->server_type == SILC_ROUTER ?
2730 TRUE : FALSE, id_entry->id, id);
2732 /* Remove client from channel */
2733 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2738 /* If the channel does not exist anymore we won't send anything */
2742 /* Re-generate channel key */
2743 silc_server_create_channel_key(server, channel, 0);
2745 /* Encode channel key payload to be distributed on the channel */
2747 silc_channel_key_payload_encode(len, tmp,
2748 strlen(channel->channel_key->cipher->name),
2749 channel->channel_key->cipher->name,
2750 channel->key_len / 8, channel->key);
2752 /* If we are normal server then we will send it to our router. If we
2753 are router we will send it to all local servers that has clients on
2755 if (server->server_type == SILC_SERVER) {
2756 if (!server->standalone)
2757 silc_server_packet_send(server,
2758 cmd->server->router->connection,
2759 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2765 /* Send to locally connected clients on the channel */
2766 silc_server_packet_send_local_channel(server, channel,
2767 SILC_PACKET_CHANNEL_KEY, 0,
2768 packet->data, packet->len, FALSE);
2770 silc_buffer_free(packet);
2774 silc_server_command_free(cmd);
2777 /* Server side of command USERS. Resolves clients and their USERS currently
2778 joined on the requested channel. The list of Client ID's and their modes
2779 on the channel is sent back. */
2781 SILC_SERVER_CMD_FUNC(users)
2783 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2784 SilcServer server = cmd->server;
2785 SilcChannelEntry channel;
2786 SilcChannelClientEntry chl;
2789 unsigned char *channel_id;
2790 unsigned int channel_id_len;
2791 SilcBuffer client_id_list;
2792 SilcBuffer client_mode_list;
2794 unsigned char lc[4];
2795 unsigned int list_count = 0;
2796 unsigned short ident = silc_command_get_ident(cmd->payload);
2798 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
2800 /* Get Channel ID */
2801 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
2803 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2804 SILC_STATUS_ERR_NO_CHANNEL_ID);
2807 id = silc_id_payload_parse_id(channel_id, channel_id_len);
2809 /* If we are server and we don't know about this channel we will send
2810 the command to our router. If we know about the channel then we also
2811 have the list of users already. */
2812 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2814 if (server->server_type == SILC_SERVER && !server->standalone &&
2818 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2819 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2821 /* Send USERS command */
2822 silc_server_packet_send(server, server->router->connection,
2823 SILC_PACKET_COMMAND, cmd->packet->flags,
2824 tmpbuf->data, tmpbuf->len, TRUE);
2826 /* Reprocess this packet after received reply */
2827 silc_server_command_pending(server, SILC_COMMAND_USERS,
2828 silc_command_get_ident(cmd->payload),
2829 silc_server_command_users, (void *)cmd);
2830 cmd->pending = TRUE;
2831 silc_command_set_ident(cmd->payload, ident);
2833 silc_buffer_free(tmpbuf);
2838 /* We are router and we will check the global list as well. */
2839 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2841 /* Channel really does not exist */
2842 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2843 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2848 /* Assemble the lists now */
2850 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2851 silc_list_count(channel->user_list));
2852 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2854 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2855 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2857 silc_list_start(channel->user_list);
2858 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2860 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2861 silc_buffer_put(client_id_list, idp->data, idp->len);
2862 silc_buffer_pull(client_id_list, idp->len);
2863 silc_buffer_free(idp);
2865 /* Client's mode on channel */
2866 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2867 silc_buffer_pull(client_mode_list, 4);
2871 silc_buffer_push(client_id_list,
2872 client_id_list->data - client_id_list->head);
2873 silc_buffer_push(client_mode_list,
2874 client_mode_list->data - client_mode_list->head);
2877 SILC_PUT32_MSB(list_count, lc);
2880 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
2881 SILC_STATUS_OK, 0, 4,
2882 2, channel_id, channel_id_len,
2884 4, client_id_list->data,
2885 client_id_list->len,
2886 5, client_mode_list->data,
2887 client_mode_list->len);
2888 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2889 packet->data, packet->len, FALSE);
2891 silc_buffer_free(packet);
2892 silc_buffer_free(client_id_list);
2893 silc_buffer_free(client_mode_list);
2897 silc_server_command_free(cmd);