5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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 void silc_server_command_send_users(SilcServer server,
41 SilcSocketConnection sock,
42 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(users, USERS, 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, command, \
89 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
90 silc_server_command_free(cmd); \
94 silc_server_command_send_status_reply(cmd, command, \
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_server_command_alloc();
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 /* Allocate Command Context */
193 SilcServerCommandContext silc_server_command_alloc()
195 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
200 /* Free's the command context allocated before executing the command */
202 void silc_server_command_free(SilcServerCommandContext ctx)
205 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
207 if (ctx->users < 1) {
209 silc_command_free_payload(ctx->payload);
211 silc_packet_context_free(ctx->packet);
216 /* Duplicate Command Context by adding reference counter. The context won't
217 be free'd untill it hits zero. */
219 SilcServerCommandContext
220 silc_server_command_dup(SilcServerCommandContext ctx)
223 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
228 /* Add new pending command to be executed when reply to a command has been
229 received. The `reply_cmd' is the command that will call the `callback'
230 with `context' when reply has been received. If `ident' is non-zero
231 the `callback' will be executed when received reply with command
232 identifier `ident'. */
234 void silc_server_command_pending(SilcServer server,
235 SilcCommand reply_cmd,
236 unsigned short ident,
237 SilcServerPendingDestructor destructor,
238 SilcCommandCb callback,
241 SilcServerCommandPending *reply;
243 reply = silc_calloc(1, sizeof(*reply));
244 reply->reply_cmd = reply_cmd;
245 reply->ident = ident;
246 reply->context = context;
247 reply->callback = callback;
248 reply->destructor = destructor;
249 silc_dlist_add(server->pending_commands, reply);
252 /* Deletes pending command by reply command type. */
254 void silc_server_command_pending_del(SilcServer server,
255 SilcCommand reply_cmd,
256 unsigned short ident)
258 SilcServerCommandPending *r;
260 silc_dlist_start(server->pending_commands);
261 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
262 if (r->reply_cmd == reply_cmd && r->ident == ident) {
263 silc_dlist_del(server->pending_commands, r);
269 /* Checks for pending commands and marks callbacks to be called from
270 the command reply function. Returns TRUE if there were pending command. */
272 int silc_server_command_pending_check(SilcServer server,
273 SilcServerCommandReplyContext ctx,
275 unsigned short ident)
277 SilcServerCommandPending *r;
279 silc_dlist_start(server->pending_commands);
280 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
281 if (r->reply_cmd == command && r->ident == ident) {
282 ctx->context = r->context;
283 ctx->callback = r->callback;
284 ctx->destructor = r->destructor;
293 /* Destructor function for pending callbacks. This is called when using
294 pending commands to free the context given for the pending command. */
296 static void silc_server_command_destructor(void *context)
298 silc_server_command_free((SilcServerCommandContext)context);
301 /* Sends simple status message as command reply packet */
304 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
306 SilcCommandStatus status)
310 SILC_LOG_DEBUG(("Sending command status %d", status));
312 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
313 silc_server_packet_send(cmd->server, cmd->sock,
314 SILC_PACKET_COMMAND_REPLY, 0,
315 buffer->data, buffer->len, FALSE);
316 silc_buffer_free(buffer);
319 /* Sends command status reply with one extra argument. The argument
320 type must be sent as argument. */
323 silc_server_command_send_status_data(SilcServerCommandContext cmd,
325 SilcCommandStatus status,
326 unsigned int arg_type,
328 unsigned int arg_len)
332 SILC_LOG_DEBUG(("Sending command status %d", status));
334 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
335 arg_type, arg, arg_len);
336 silc_server_packet_send(cmd->server, cmd->sock,
337 SILC_PACKET_COMMAND_REPLY, 0,
338 buffer->data, buffer->len, FALSE);
339 silc_buffer_free(buffer);
342 /******************************************************************************
346 ******************************************************************************/
349 silc_server_command_whois_parse(SilcServerCommandContext cmd,
350 SilcClientID ***client_id,
351 unsigned int *client_id_count,
359 unsigned int argc = silc_argument_get_arg_num(cmd->args);
362 /* If client ID is in the command it must be used instead of nickname */
363 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
365 /* No ID, get the nickname@server string and parse it. */
366 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
368 if (strchr(tmp, '@')) {
369 len = strcspn(tmp, "@");
370 *nickname = silc_calloc(len + 1, sizeof(char));
371 memcpy(*nickname, tmp, len);
372 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
373 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
375 *nickname = strdup(tmp);
378 silc_server_command_send_status_reply(cmd, command,
379 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
383 /* Command includes ID, we must use that. Also check whether the command
384 has more than one ID set - take them all. */
386 *client_id = silc_calloc(1, sizeof(**client_id));
387 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
388 if ((*client_id)[0] == NULL) {
389 silc_free(*client_id);
392 *client_id_count = 1;
394 /* Take all ID's from the command packet */
396 for (k = 1, i = 4; i < argc + 1; i++) {
397 tmp = silc_argument_get_arg_type(cmd->args, i, &len);
399 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
400 (*client_id_count + 1));
401 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
402 if ((*client_id)[k] == NULL) {
403 /* Cleanup all and fail */
404 for (i = 0; i < *client_id_count; i++)
405 silc_free((*client_id)[i]);
406 silc_free(*client_id);
409 (*client_id_count)++;
415 /* Command includes ID, use that */
418 /* Get the max count of reply messages allowed */
419 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
429 silc_server_command_whois_check(SilcServerCommandContext cmd,
430 SilcClientEntry *clients,
431 unsigned int clients_count)
433 SilcServer server = cmd->server;
435 SilcClientEntry entry;
437 for (i = 0; i < clients_count; i++) {
440 if (!entry->nickname || !entry->username) {
442 unsigned short old_ident;
447 old_ident = silc_command_get_ident(cmd->payload);
448 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
449 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
451 /* Send WHOIS command */
452 silc_server_packet_send(server, entry->router->connection,
453 SILC_PACKET_COMMAND, cmd->packet->flags,
454 tmpbuf->data, tmpbuf->len, TRUE);
456 /* Reprocess this packet after received reply */
457 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
458 silc_command_get_ident(cmd->payload),
459 silc_server_command_destructor,
460 silc_server_command_whois,
461 silc_server_command_dup(cmd));
464 silc_command_set_ident(cmd->payload, old_ident);
466 silc_buffer_free(tmpbuf);
475 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
476 SilcClientEntry *clients,
477 unsigned int clients_count)
479 SilcServer server = cmd->server;
481 int i, count = 0, len;
482 SilcBuffer packet, idp;
483 SilcClientEntry entry;
484 SilcCommandStatus status;
485 unsigned short ident = silc_command_get_ident(cmd->payload);
487 status = SILC_STATUS_OK;
488 if (clients_count > 1)
489 status = SILC_STATUS_LIST_START;
491 for (i = 0; i < clients_count; i++) {
494 if (count && i - 1 == count)
497 if (clients_count > 2)
498 status = SILC_STATUS_LIST_ITEM;
500 if (clients_count > 1 && i == clients_count - 1)
501 status = SILC_STATUS_LIST_END;
503 /* Sanity check, however these should never fail. However, as
504 this sanity check has been added here they have failed. */
505 if (!entry->nickname || !entry->username)
508 /* Send WHOIS reply */
509 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
510 tmp = silc_argument_get_first_arg(cmd->args, NULL);
514 char nh[256], uh[256];
515 unsigned char idle[4];
516 SilcSocketConnection hsock;
518 memset(uh, 0, sizeof(uh));
519 memset(nh, 0, sizeof(nh));
521 strncat(nh, entry->nickname, strlen(entry->nickname));
522 if (!strchr(entry->nickname, '@')) {
524 len = entry->router ? strlen(entry->router->server_name) :
525 strlen(server->server_name);
526 strncat(nh, entry->router ? entry->router->server_name :
527 server->server_name, len);
530 strncat(uh, entry->username, strlen(entry->username));
531 if (!strchr(entry->username, '@')) {
533 hsock = (SilcSocketConnection)entry->connection;
534 len = strlen(hsock->hostname);
535 strncat(uh, hsock->hostname, len);
538 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
543 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
545 2, idp->data, idp->len,
549 strlen(entry->userinfo),
553 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
555 2, idp->data, idp->len,
561 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
562 0, packet->data, packet->len, FALSE);
564 silc_buffer_free(packet);
565 silc_buffer_free(idp);
570 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
572 SilcServer server = cmd->server;
573 char *nick = NULL, *server_name = NULL;
574 int count = 0, clients_count = 0;
575 SilcClientEntry *clients = NULL, entry;
576 SilcClientID **client_id = NULL;
577 unsigned int client_id_count = 0;
580 /* Protocol dictates that we must always send the received WHOIS request
581 to our router if we are normal server, so let's do it now unless we
582 are standalone. We will not send any replies to the client until we
583 have received reply from the router. */
584 if (server->server_type == SILC_SERVER &&
585 !cmd->pending && !server->standalone) {
587 unsigned short old_ident;
589 old_ident = silc_command_get_ident(cmd->payload);
590 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
591 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
593 /* Send WHOIS command to our router */
594 silc_server_packet_send(server, (SilcSocketConnection)
595 server->router->connection,
596 SILC_PACKET_COMMAND, cmd->packet->flags,
597 tmpbuf->data, tmpbuf->len, TRUE);
599 /* Reprocess this packet after received reply from router */
600 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
601 silc_command_get_ident(cmd->payload),
602 silc_server_command_destructor,
603 silc_server_command_whois,
604 silc_server_command_dup(cmd));
607 silc_command_set_ident(cmd->payload, old_ident);
609 silc_buffer_free(tmpbuf);
613 /* We are ready to process the command request. Let's search for the
614 requested client and send reply to the requesting client. */
616 /* Parse the whois request */
617 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
618 &nick, &server_name, &count,
622 /* Get all clients matching that ID or nickname from local list */
623 if (client_id_count) {
624 /* Check all Client ID's received in the command packet */
625 for (i = 0; i < client_id_count; i++) {
626 entry = silc_idlist_find_client_by_id(server->local_list,
629 clients = silc_realloc(clients, sizeof(*clients) *
630 (clients_count + 1));
631 clients[clients_count++] = entry;
635 clients = silc_idlist_get_clients_by_nickname(server->local_list,
640 /* Check global list as well */
642 if (client_id_count) {
643 /* Check all Client ID's received in the command packet */
644 for (i = 0; i < client_id_count; i++) {
645 entry = silc_idlist_find_client_by_id(server->global_list,
648 clients = silc_realloc(clients, sizeof(*clients) *
649 (clients_count + 1));
650 clients[clients_count++] = entry;
654 clients = silc_idlist_get_clients_by_nickname(server->global_list,
661 /* Such client(s) really does not exist in the SILC network. */
662 if (!client_id_count) {
663 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
664 SILC_STATUS_ERR_NO_SUCH_NICK,
665 3, nick, strlen(nick));
667 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
668 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
669 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
670 2, idp->data, idp->len);
671 silc_buffer_free(idp);
676 /* Router always finds the client entry if it exists in the SILC network.
677 However, it might be incomplete entry and does not include all the
678 mandatory fields that WHOIS command reply requires. Check for these and
679 make query from the server who owns the client if some fields are
681 if (!silc_server_command_whois_check(cmd, clients, clients_count))
684 /* Send the command reply to the client */
685 silc_server_command_whois_send_reply(cmd, clients, clients_count);
688 if (client_id_count) {
689 for (i = 0; i < client_id_count; i++)
690 silc_free(client_id[i]);
691 silc_free(client_id);
698 silc_free(server_name);
702 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
704 SilcServer server = cmd->server;
705 char *nick = NULL, *server_name = NULL;
706 int count = 0, clients_count = 0;
707 SilcClientEntry *clients = NULL, entry;
708 SilcClientID **client_id = NULL;
709 unsigned int client_id_count = 0;
712 /* Parse the whois request */
713 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
714 &nick, &server_name, &count,
718 /* Process the command request. Let's search for the requested client and
719 send reply to the requesting server. */
721 if (client_id_count) {
722 /* Check all Client ID's received in the command packet */
723 for (i = 0; i < client_id_count; i++) {
724 entry = silc_idlist_find_client_by_id(server->local_list,
727 clients = silc_realloc(clients, sizeof(*clients) *
728 (clients_count + 1));
729 clients[clients_count++] = entry;
733 clients = silc_idlist_get_clients_by_nickname(server->local_list,
737 clients = silc_idlist_get_clients_by_hash(server->local_list,
738 nick, server->md5hash,
742 /* If we are router we will check our global list as well. */
743 if (!clients && server->server_type == SILC_ROUTER) {
744 if (client_id_count) {
745 /* Check all Client ID's received in the command packet */
746 for (i = 0; i < client_id_count; i++) {
747 entry = silc_idlist_find_client_by_id(server->global_list,
750 clients = silc_realloc(clients, sizeof(*clients) *
751 (clients_count + 1));
752 clients[clients_count++] = entry;
756 clients = silc_idlist_get_clients_by_nickname(server->global_list,
760 clients = silc_idlist_get_clients_by_hash(server->global_list,
761 nick, server->md5hash,
767 /* Such a client really does not exist in the SILC network. */
768 if (!client_id_count) {
769 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
770 SILC_STATUS_ERR_NO_SUCH_NICK,
771 3, nick, strlen(nick));
773 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
774 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
775 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
776 2, idp->data, idp->len);
777 silc_buffer_free(idp);
782 /* Router always finds the client entry if it exists in the SILC network.
783 However, it might be incomplete entry and does not include all the
784 mandatory fields that WHOIS command reply requires. Check for these and
785 make query from the server who owns the client if some fields are
787 if (!silc_server_command_whois_check(cmd, clients, clients_count))
790 /* Send the command reply to the client */
791 silc_server_command_whois_send_reply(cmd, clients, clients_count);
794 if (client_id_count) {
795 for (i = 0; i < client_id_count; i++)
796 silc_free(client_id[i]);
797 silc_free(client_id);
804 silc_free(server_name);
807 /* Server side of command WHOIS. Processes user's query and sends found
808 results as command replies back to the client. */
810 SILC_SERVER_CMD_FUNC(whois)
812 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
814 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
816 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
817 silc_server_command_whois_from_client(cmd);
819 silc_server_command_whois_from_server(cmd);
821 silc_server_command_free(cmd);
824 SILC_SERVER_CMD_FUNC(whowas)
828 /******************************************************************************
832 ******************************************************************************/
834 /* Checks that all mandatory fields are present. If not then send WHOIS
835 request to the server who owns the client. We use WHOIS because we want
836 to get as much information as possible at once. */
839 silc_server_command_identify_check(SilcServerCommandContext cmd,
840 SilcClientEntry *clients,
841 unsigned int clients_count)
843 SilcServer server = cmd->server;
845 SilcClientEntry entry;
847 for (i = 0; i < clients_count; i++) {
850 if (!entry->nickname) {
852 unsigned short old_ident;
857 old_ident = silc_command_get_ident(cmd->payload);
858 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
859 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
860 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
862 /* Send WHOIS request. We send WHOIS since we're doing the requesting
863 now anyway so make it a good one. */
864 silc_server_packet_send(server, entry->router->connection,
865 SILC_PACKET_COMMAND, cmd->packet->flags,
866 tmpbuf->data, tmpbuf->len, TRUE);
868 /* Reprocess this packet after received reply */
869 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
870 silc_command_get_ident(cmd->payload),
871 silc_server_command_destructor,
872 silc_server_command_identify,
873 silc_server_command_dup(cmd));
877 /* Put old data back to the Command Payload we just changed */
878 silc_command_set_ident(cmd->payload, old_ident);
879 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
881 silc_buffer_free(tmpbuf);
890 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
891 SilcClientEntry *clients,
892 unsigned int clients_count)
894 SilcServer server = cmd->server;
896 int i, count = 0, len;
897 SilcBuffer packet, idp;
898 SilcClientEntry entry;
899 SilcCommandStatus status;
900 unsigned short ident = silc_command_get_ident(cmd->payload);
902 status = SILC_STATUS_OK;
903 if (clients_count > 1)
904 status = SILC_STATUS_LIST_START;
906 for (i = 0; i < clients_count; i++) {
909 if (count && i - 1 == count)
912 if (clients_count > 2)
913 status = SILC_STATUS_LIST_ITEM;
915 if (clients_count > 1 && i == clients_count - 1)
916 status = SILC_STATUS_LIST_END;
918 /* Send IDENTIFY reply */
919 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
920 tmp = silc_argument_get_first_arg(cmd->args, NULL);
924 char nh[256], uh[256];
925 SilcSocketConnection hsock;
927 memset(uh, 0, sizeof(uh));
928 memset(nh, 0, sizeof(nh));
930 strncat(nh, entry->nickname, strlen(entry->nickname));
931 if (!strchr(entry->nickname, '@')) {
933 len = entry->router ? strlen(entry->router->server_name) :
934 strlen(server->server_name);
935 strncat(nh, entry->router ? entry->router->server_name :
936 server->server_name, len);
939 if (!entry->username) {
940 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
941 SILC_STATUS_OK, ident, 2,
942 2, idp->data, idp->len,
945 strncat(uh, entry->username, strlen(entry->username));
946 if (!strchr(entry->username, '@')) {
948 hsock = (SilcSocketConnection)entry->connection;
949 len = strlen(hsock->hostname);
950 strncat(uh, hsock->hostname, len);
953 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
954 SILC_STATUS_OK, ident, 3,
955 2, idp->data, idp->len,
960 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
961 0, packet->data, packet->len, FALSE);
963 silc_buffer_free(packet);
964 silc_buffer_free(idp);
970 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
972 SilcServer server = cmd->server;
973 char *nick = NULL, *server_name = NULL;
974 int count = 0, clients_count = 0;
975 SilcClientEntry *clients = NULL, entry;
976 SilcClientID **client_id = NULL;
977 unsigned int client_id_count = 0;
980 /* Protocol dictates that we must always send the received IDENTIFY request
981 to our router if we are normal server, so let's do it now unless we
982 are standalone. We will not send any replies to the client until we
983 have received reply from the router. */
984 if (server->server_type == SILC_SERVER &&
985 !cmd->pending && !server->standalone) {
987 unsigned short old_ident;
989 old_ident = silc_command_get_ident(cmd->payload);
990 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
991 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
993 /* Send IDENTIFY command to our router */
994 silc_server_packet_send(server, (SilcSocketConnection)
995 server->router->connection,
996 SILC_PACKET_COMMAND, cmd->packet->flags,
997 tmpbuf->data, tmpbuf->len, TRUE);
999 /* Reprocess this packet after received reply from router */
1000 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1001 silc_command_get_ident(cmd->payload),
1002 silc_server_command_destructor,
1003 silc_server_command_identify,
1004 silc_server_command_dup(cmd));
1005 cmd->pending = TRUE;
1007 silc_command_set_ident(cmd->payload, old_ident);
1009 silc_buffer_free(tmpbuf);
1013 /* We are ready to process the command request. Let's search for the
1014 requested client and send reply to the requesting client. */
1016 /* Parse the IDENTIFY request */
1017 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1018 &nick, &server_name, &count,
1019 SILC_COMMAND_IDENTIFY))
1022 /* Get all clients matching that ID or nickname from local list */
1023 if (client_id_count) {
1024 /* Check all Client ID's received in the command packet */
1025 for (i = 0; i < client_id_count; i++) {
1026 entry = silc_idlist_find_client_by_id(server->local_list,
1027 client_id[i], NULL);
1029 clients = silc_realloc(clients, sizeof(*clients) *
1030 (clients_count + 1));
1031 clients[clients_count++] = entry;
1035 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1040 /* Check global list as well */
1042 if (client_id_count) {
1043 /* Check all Client ID's received in the command packet */
1044 for (i = 0; i < client_id_count; i++) {
1045 entry = silc_idlist_find_client_by_id(server->global_list,
1046 client_id[i], NULL);
1048 clients = silc_realloc(clients, sizeof(*clients) *
1049 (clients_count + 1));
1050 clients[clients_count++] = entry;
1054 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1061 /* Such a client really does not exist in the SILC network. */
1062 if (!client_id_count) {
1063 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1064 SILC_STATUS_ERR_NO_SUCH_NICK,
1065 3, nick, strlen(nick));
1067 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1068 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1069 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1070 2, idp->data, idp->len);
1071 silc_buffer_free(idp);
1076 /* Check that all mandatory fields are present and request those data
1077 from the server who owns the client if necessary. */
1078 if (!silc_server_command_identify_check(cmd, clients, clients_count))
1081 /* Send the command reply to the client */
1082 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1085 if (client_id_count) {
1086 for (i = 0; i < client_id_count; i++)
1087 silc_free(client_id[i]);
1088 silc_free(client_id);
1095 silc_free(server_name);
1099 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1101 SilcServer server = cmd->server;
1102 char *nick = NULL, *server_name = NULL;
1103 int count = 0, clients_count = 0;
1104 SilcClientEntry *clients = NULL, entry;
1105 SilcClientID **client_id = NULL;
1106 unsigned int client_id_count = 0;
1109 /* Parse the IDENTIFY request */
1110 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1111 &nick, &server_name, &count,
1112 SILC_COMMAND_IDENTIFY))
1115 /* Process the command request. Let's search for the requested client and
1116 send reply to the requesting server. */
1118 if (client_id_count) {
1119 /* Check all Client ID's received in the command packet */
1120 for (i = 0; i < client_id_count; i++) {
1121 entry = silc_idlist_find_client_by_id(server->local_list,
1122 client_id[i], NULL);
1124 clients = silc_realloc(clients, sizeof(*clients) *
1125 (clients_count + 1));
1126 clients[clients_count++] = entry;
1130 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1134 clients = silc_idlist_get_clients_by_hash(server->local_list,
1135 nick, server->md5hash,
1139 /* If we are router we will check our global list as well. */
1140 if (!clients && server->server_type == SILC_ROUTER) {
1141 if (client_id_count) {
1142 /* Check all Client ID's received in the command packet */
1143 for (i = 0; i < client_id_count; i++) {
1144 entry = silc_idlist_find_client_by_id(server->global_list,
1145 client_id[i], NULL);
1147 clients = silc_realloc(clients, sizeof(*clients) *
1148 (clients_count + 1));
1149 clients[clients_count++] = entry;
1153 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1157 clients = silc_idlist_get_clients_by_hash(server->global_list,
1158 nick, server->md5hash,
1164 /* Such a client really does not exist in the SILC network. */
1165 if (!client_id_count) {
1166 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1167 SILC_STATUS_ERR_NO_SUCH_NICK,
1168 3, nick, strlen(nick));
1170 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1171 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1172 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1173 2, idp->data, idp->len);
1174 silc_buffer_free(idp);
1179 /* Check that all mandatory fields are present and request those data
1180 from the server who owns the client if necessary. */
1181 if (!silc_server_command_identify_check(cmd, clients, clients_count))
1184 /* Send the command reply */
1185 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1188 if (client_id_count) {
1189 for (i = 0; i < client_id_count; i++)
1190 silc_free(client_id[i]);
1191 silc_free(client_id);
1198 silc_free(server_name);
1201 SILC_SERVER_CMD_FUNC(identify)
1203 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1205 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1207 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1208 silc_server_command_identify_from_client(cmd);
1210 silc_server_command_identify_from_server(cmd);
1212 silc_server_command_free(cmd);
1215 /* Checks string for bad characters and returns TRUE if they are found. */
1217 static int silc_server_command_bad_chars(char *nick)
1219 if (strchr(nick, '\\')) return TRUE;
1220 if (strchr(nick, '\"')) return TRUE;
1221 if (strchr(nick, '´')) return TRUE;
1222 if (strchr(nick, '`')) return TRUE;
1223 if (strchr(nick, '\'')) return TRUE;
1224 if (strchr(nick, '*')) return TRUE;
1225 if (strchr(nick, '/')) return TRUE;
1226 if (strchr(nick, '@')) return TRUE;
1231 /* Server side of command NICK. Sets nickname for user. Setting
1232 nickname causes generation of a new client ID for the client. The
1233 new client ID is sent to the client after changing the nickname. */
1235 SILC_SERVER_CMD_FUNC(nick)
1237 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1238 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1239 SilcServer server = cmd->server;
1240 SilcBuffer packet, nidp, oidp;
1241 SilcClientID *new_id;
1244 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1246 /* Check nickname */
1247 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1248 if (silc_server_command_bad_chars(nick) == TRUE) {
1249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1250 SILC_STATUS_ERR_BAD_NICKNAME);
1254 /* Create new Client ID */
1255 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1256 cmd->server->md5hash, nick,
1259 /* Send notify about nickname change to our router. We send the new
1260 ID and ask to replace it with the old one. If we are router the
1261 packet is broadcasted. */
1262 if (!server->standalone)
1263 silc_server_send_replace_id(server, server->router->connection,
1264 server->server_type == SILC_SERVER ?
1265 FALSE : TRUE, client->id,
1266 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1267 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1269 /* Remove old cache entry */
1270 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1273 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1277 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1278 silc_free(client->id);
1281 /* Save the nickname as this client is our local client */
1282 if (client->nickname)
1283 silc_free(client->nickname);
1285 client->nickname = strdup(nick);
1286 client->id = new_id;
1288 /* Update client cache */
1289 silc_idcache_add(server->local_list->clients, client->nickname,
1290 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1292 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1294 /* Send NICK_CHANGE notify */
1295 silc_server_send_notify_on_channels(server, client,
1296 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1297 oidp->data, oidp->len,
1298 nidp->data, nidp->len);
1300 /* Send the new Client ID as reply command back to client */
1301 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1302 SILC_STATUS_OK, 0, 1,
1303 2, nidp->data, nidp->len);
1304 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1305 0, packet->data, packet->len, FALSE);
1307 silc_buffer_free(packet);
1308 silc_buffer_free(nidp);
1309 silc_buffer_free(oidp);
1312 silc_server_command_free(cmd);
1315 SILC_SERVER_CMD_FUNC(list)
1319 /* Server side of TOPIC command. Sets topic for channel and/or returns
1320 current topic to client. */
1322 SILC_SERVER_CMD_FUNC(topic)
1324 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1325 SilcServer server = cmd->server;
1326 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1327 SilcChannelID *channel_id;
1328 SilcChannelEntry channel;
1329 SilcChannelClientEntry chl;
1330 SilcBuffer packet, idp;
1332 unsigned int argc, tmp_len;
1334 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1336 argc = silc_argument_get_arg_num(cmd->args);
1338 /* Get Channel ID */
1339 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1342 SILC_STATUS_ERR_NO_CHANNEL_ID);
1345 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1348 SILC_STATUS_ERR_NO_CHANNEL_ID);
1352 /* Check whether the channel exists */
1353 channel = silc_idlist_find_channel_by_id(server->local_list,
1356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1357 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1363 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1365 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1366 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1370 if (strlen(tmp) > 256) {
1371 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1372 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1376 /* See whether has rights to change topic */
1377 silc_list_start(channel->user_list);
1378 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1379 if (chl->client == client) {
1380 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1381 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1382 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1390 /* Set the topic for channel */
1392 silc_free(channel->topic);
1393 channel->topic = strdup(tmp);
1395 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1397 /* Send notify about topic change to all clients on the channel */
1398 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1399 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1400 idp->data, idp->len,
1401 channel->topic, strlen(channel->topic));
1402 silc_buffer_free(idp);
1405 /* Send the topic to client as reply packet */
1406 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1408 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1409 SILC_STATUS_OK, 0, 2,
1410 2, idp->data, idp->len,
1412 strlen(channel->topic));
1414 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1415 SILC_STATUS_OK, 0, 1,
1416 2, idp->data, idp->len);
1417 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1418 0, packet->data, packet->len, FALSE);
1420 silc_buffer_free(packet);
1421 silc_buffer_free(idp);
1422 silc_free(channel_id);
1425 silc_server_command_free(cmd);
1428 /* Server side of INVITE command. Invites some client to join some channel. */
1430 SILC_SERVER_CMD_FUNC(invite)
1432 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1433 SilcServer server = cmd->server;
1434 SilcSocketConnection sock = cmd->sock, dest_sock;
1435 SilcClientEntry sender, dest;
1436 SilcClientID *dest_id;
1437 SilcChannelEntry channel;
1438 SilcChannelID *channel_id;
1443 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1445 /* Get destination ID */
1446 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1448 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1449 SILC_STATUS_ERR_NO_CLIENT_ID);
1452 dest_id = silc_id_payload_parse_id(tmp, len);
1454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1455 SILC_STATUS_ERR_NO_CLIENT_ID);
1459 /* Get Channel ID */
1460 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1462 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1463 SILC_STATUS_ERR_NO_CHANNEL_ID);
1466 channel_id = silc_id_payload_parse_id(tmp, len);
1468 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1469 SILC_STATUS_ERR_NO_CHANNEL_ID);
1473 /* Check whether the channel exists */
1474 channel = silc_idlist_find_channel_by_id(server->local_list,
1477 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1478 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1482 /* Check whether the sender of this command is on the channel. */
1483 sender = (SilcClientEntry)sock->user_data;
1484 if (!silc_server_client_on_channel(sender, channel)) {
1485 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1486 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1490 /* Check whether the channel is invite-only channel. If yes then the
1491 sender of this command must be at least channel operator. */
1492 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1493 SilcChannelClientEntry chl;
1495 silc_list_start(channel->user_list);
1496 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1497 if (chl->client == sender) {
1498 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1500 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1507 /* Find the connection data for the destination. If it is local we will
1508 send it directly otherwise we will send it to router for routing. */
1509 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1511 dest_sock = (SilcSocketConnection)dest->connection;
1513 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1515 /* Check whether the requested client is already on the channel. */
1516 /* XXX if we are normal server we don't know about global clients on
1517 the channel thus we must request it (USERS command), check from
1518 local cache as well. */
1519 if (silc_server_client_on_channel(dest, channel)) {
1520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1521 SILC_STATUS_ERR_USER_ON_CHANNEL);
1525 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1527 /* Send notify to the client that is invited to the channel */
1528 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1529 SILC_NOTIFY_TYPE_INVITE, 2,
1530 sidp->data, sidp->len, tmp, len);
1532 /* Send command reply */
1533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1536 silc_buffer_free(sidp);
1539 silc_server_command_free(cmd);
1542 /* Quits connection to client. This gets called if client won't
1543 close the connection even when it has issued QUIT command. */
1545 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1547 SilcServer server = (SilcServer)context;
1548 SilcSocketConnection sock = server->sockets[fd];
1550 /* Free all client specific data, such as client entry and entires
1551 on channels this client may be on. */
1552 silc_server_free_sock_user_data(server, sock);
1554 /* Close the connection on our side */
1555 silc_server_close_connection(server, sock);
1558 /* Quits SILC session. This is the normal way to disconnect client. */
1560 SILC_SERVER_CMD_FUNC(quit)
1562 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1563 SilcServer server = cmd->server;
1564 SilcSocketConnection sock = cmd->sock;
1566 SILC_LOG_DEBUG(("Start"));
1568 /* We quit the connection with little timeout */
1569 silc_task_register(server->timeout_queue, sock->sock,
1570 silc_server_command_quit_cb, server,
1571 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1573 silc_server_command_free(cmd);
1576 SILC_SERVER_CMD_FUNC(kill)
1580 /* Server side of command INFO. This sends information about us to
1581 the client. If client requested specific server we will send the
1582 command to that server. */
1584 SILC_SERVER_CMD_FUNC(info)
1586 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1587 SilcServer server = cmd->server;
1588 SilcBuffer packet, idp;
1589 char info_string[256], *dest_server;
1591 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1593 /* Get server name */
1594 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1596 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1597 SILC_STATUS_ERR_NO_SUCH_SERVER);
1601 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1602 /* Send our reply */
1603 memset(info_string, 0, sizeof(info_string));
1604 snprintf(info_string, sizeof(info_string),
1605 "location: %s server: %s admin: %s <%s>",
1606 server->config->admin_info->location,
1607 server->config->admin_info->server_type,
1608 server->config->admin_info->admin_name,
1609 server->config->admin_info->admin_email);
1611 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1613 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1614 SILC_STATUS_OK, 0, 2,
1615 2, idp->data, idp->len,
1617 strlen(info_string));
1618 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1619 packet->data, packet->len, FALSE);
1621 silc_buffer_free(packet);
1622 silc_buffer_free(idp);
1624 /* Send this command to the requested server */
1626 if (server->server_type == SILC_SERVER && !server->standalone) {
1630 if (server->server_type == SILC_ROUTER) {
1636 silc_server_command_free(cmd);
1639 SILC_SERVER_CMD_FUNC(connect)
1643 /* Server side of command PING. This just replies to the ping. */
1645 SILC_SERVER_CMD_FUNC(ping)
1647 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1648 SilcServer server = cmd->server;
1653 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1656 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1658 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1659 SILC_STATUS_ERR_NO_SERVER_ID);
1662 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1666 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1667 /* Send our reply */
1668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1671 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1672 SILC_STATUS_ERR_NO_SUCH_SERVER);
1679 silc_server_command_free(cmd);
1682 SILC_SERVER_CMD_FUNC(oper)
1686 /* Assembles USERS command and executes it. This is called when client
1687 joins to a channel and we wan't to send USERS command reply to the
1690 void silc_server_command_send_users(SilcServer server,
1691 SilcSocketConnection sock,
1692 SilcChannelEntry channel,
1695 SilcServerCommandContext cmd;
1696 SilcBuffer buffer, idp;
1697 SilcPacketContext *packet = silc_packet_context_alloc();
1699 SILC_LOG_DEBUG(("Start"));
1701 /* Create USERS command packet and process it. */
1702 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1703 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1704 1, idp->data, idp->len);
1706 packet->buffer = silc_buffer_copy(buffer);
1707 packet->sock = sock;
1708 packet->type = SILC_PACKET_COMMAND;
1710 cmd = silc_server_command_alloc();
1711 cmd->payload = silc_command_payload_parse(buffer);
1712 if (!cmd->payload) {
1714 silc_buffer_free(buffer);
1715 silc_buffer_free(idp);
1716 silc_packet_context_free(packet);
1719 cmd->args = silc_command_get_args(cmd->payload);
1720 cmd->server = server;
1722 cmd->packet = silc_packet_context_dup(packet);
1723 cmd->pending = FALSE;
1726 /* If this function was called from pending command then instead of
1727 processing the command now, register a pending command callback which
1728 will process it after we've received the automatic USERS command
1730 silc_server_command_pending(server, SILC_COMMAND_USERS, 0,
1731 silc_server_command_destructor,
1732 silc_server_command_users,
1733 silc_server_command_dup(cmd));
1734 cmd->pending = TRUE;
1738 /* Process USERS command. */
1739 silc_server_command_users((void *)cmd);
1742 silc_buffer_free(buffer);
1743 silc_buffer_free(idp);
1744 silc_packet_context_free(packet);
1747 /* Internal routine to join channel. The channel sent to this function
1748 has been either created or resolved from ID lists. This joins the sent
1749 client to the channel. */
1751 static void silc_server_command_join_channel(SilcServer server,
1752 SilcServerCommandContext cmd,
1753 SilcChannelEntry channel,
1754 SilcClientID *client_id,
1758 SilcSocketConnection sock = cmd->sock;
1760 unsigned int tmp_len;
1761 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1762 SilcClientEntry client;
1763 SilcChannelClientEntry chl;
1764 SilcBuffer reply, chidp, clidp, keyp;
1765 unsigned short ident = silc_command_get_ident(cmd->payload);
1767 SILC_LOG_DEBUG(("Start"));
1772 /* Get passphrase */
1773 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1775 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1776 memcpy(passphrase, tmp, tmp_len);
1780 * Check channel modes
1783 /* Check invite list if channel is invite-only channel */
1784 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1785 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1786 /* Invite list is specified. Check whether client is invited in the
1787 list. If not, then check whether it has been invited otherwise. */
1790 /* XXX client must be invited to be able to join the channel */
1794 /* Check ban list if set */
1795 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1799 /* Check the channel passphrase if set. */
1800 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1801 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1802 strlen(channel->mode_data.passphrase))) {
1803 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1804 SILC_STATUS_ERR_BAD_PASSWORD);
1809 /* Check user count limit if set. */
1810 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1811 if (silc_list_count(channel->user_list) + 1 >
1812 channel->mode_data.user_limit) {
1813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1814 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1820 * Client is allowed to join to the channel. Make it happen.
1823 /* Get the client entry */
1824 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1825 client = (SilcClientEntry)sock->user_data;
1827 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1830 /* XXX actually this is useless since router finds always cell's
1831 local clients from its local lists. */
1832 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1839 /* Check whether the client already is on the channel */
1840 if (silc_server_client_on_channel(client, channel)) {
1841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1842 SILC_STATUS_ERR_USER_ON_CHANNEL);
1846 /* Generate new channel key as protocol dictates */
1847 if (!created || !channel->channel_key)
1848 silc_server_create_channel_key(server, channel, 0);
1850 /* Send the channel key. This is broadcasted to the channel but is not
1851 sent to the client who is joining to the channel. */
1852 silc_server_send_channel_key(server, NULL, channel,
1853 server->server_type == SILC_ROUTER ?
1854 FALSE : server->standalone);
1856 /* Join the client to the channel by adding it to channel's user list.
1857 Add also the channel to client entry's channels list for fast cross-
1859 chl = silc_calloc(1, sizeof(*chl));
1861 chl->client = client;
1862 chl->channel = channel;
1863 silc_list_add(channel->user_list, chl);
1864 silc_list_add(client->channels, chl);
1866 /* Encode Client ID Payload of the original client who wants to join */
1867 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1869 /* Encode command reply packet */
1870 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1871 SILC_PUT32_MSB(channel->mode, mode);
1872 SILC_PUT32_MSB(created, tmp2);
1873 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1874 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1875 SILC_ID_CHANNEL_LEN,
1876 channel->channel_key->cipher->name,
1877 channel->key_len / 8, channel->key);
1879 if (!channel->topic) {
1881 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1882 SILC_STATUS_OK, ident, 5,
1883 2, channel->channel_name,
1884 strlen(channel->channel_name),
1885 3, chidp->data, chidp->len,
1888 6, keyp->data, keyp->len);
1891 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1892 SILC_STATUS_OK, ident, 6,
1893 2, channel->channel_name,
1894 strlen(channel->channel_name),
1895 3, chidp->data, chidp->len,
1898 6, keyp->data, keyp->len,
1900 strlen(channel->topic));
1903 /* Send command reply */
1904 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1905 reply->data, reply->len, FALSE);
1907 if (!cmd->pending) {
1908 /* Send JOIN notify to locally connected clients on the channel */
1909 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1910 SILC_NOTIFY_TYPE_JOIN, 1,
1911 clidp->data, clidp->len);
1913 /* Send NEW_CHANNEL_USER packet to our primary router */
1914 if (!server->standalone)
1915 silc_server_send_new_channel_user(server, server->router->connection,
1916 server->server_type == SILC_SERVER ?
1918 channel->id, SILC_ID_CHANNEL_LEN,
1919 client->id, SILC_ID_CLIENT_LEN);
1922 /* Send USERS command reply to the joined channel so the user sees who
1923 is currently on the channel. */
1924 silc_server_command_send_users(server, sock, channel, cmd->pending);
1926 silc_buffer_free(reply);
1927 silc_buffer_free(clidp);
1928 silc_buffer_free(chidp);
1929 silc_buffer_free(keyp);
1933 silc_free(passphrase);
1936 /* Server side of command JOIN. Joins client into requested channel. If
1937 the channel does not exist it will be created. */
1939 SILC_SERVER_CMD_FUNC(join)
1941 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1942 SilcServer server = cmd->server;
1944 char *tmp, *channel_name = NULL, *cipher = NULL;
1945 SilcChannelEntry channel;
1946 unsigned int umode = 0;
1947 int created = FALSE;
1948 SilcClientID *client_id;
1950 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1952 /* Get channel name */
1953 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1956 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1961 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1963 SILC_STATUS_ERR_BAD_CHANNEL);
1964 silc_free(channel_name);
1968 /* Get Client ID of the client who is joining to the channel */
1969 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1972 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1975 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1977 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1978 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1982 /* Get cipher name */
1983 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
1985 /* See if the channel exists */
1986 channel = silc_idlist_find_channel_by_name(server->local_list,
1987 channel_name, NULL);
1989 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1990 /* If this is coming from client the Client ID in the command packet must
1991 be same as the client's ID. */
1992 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1993 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
1994 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
1995 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1996 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2002 /* Channel not found */
2004 /* If we are standalone server we don't have a router, we just create
2005 the channel by ourselves. */
2006 if (server->standalone) {
2007 channel = silc_server_create_new_channel(server, server->id, cipher,
2008 channel_name, TRUE);
2009 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2014 /* The channel does not exist on our server. If we are normal server
2015 we will send JOIN command to our router which will handle the
2016 joining procedure (either creates the channel if it doesn't exist
2017 or joins the client to it). */
2018 if (server->server_type == SILC_SERVER) {
2020 unsigned short old_ident;
2022 old_ident = silc_command_get_ident(cmd->payload);
2023 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2024 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2026 /* Send JOIN command to our router */
2027 silc_server_packet_send(server, (SilcSocketConnection)
2028 server->router->connection,
2029 SILC_PACKET_COMMAND, cmd->packet->flags,
2030 tmpbuf->data, tmpbuf->len, TRUE);
2032 /* Reprocess this packet after received reply from router */
2033 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2034 silc_command_get_ident(cmd->payload),
2035 silc_server_command_destructor,
2036 silc_server_command_join,
2037 silc_server_command_dup(cmd));
2038 cmd->pending = TRUE;
2042 /* We are router and the channel does not seem exist so we will check
2043 our global list as well for the channel. */
2044 channel = silc_idlist_find_channel_by_name(server->global_list,
2045 channel_name, NULL);
2047 /* Channel really does not exist, create it */
2048 channel = silc_server_create_new_channel(server, server->id, cipher,
2049 channel_name, TRUE);
2050 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2057 /* Channel not found */
2059 /* If the command came from router and/or we are normal server then
2060 something went wrong with the joining as the channel was not found.
2061 We can't do anything else but ignore this. */
2062 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2063 server->server_type == SILC_SERVER)
2066 /* We are router and the channel does not seem exist so we will check
2067 our global list as well for the channel. */
2068 channel = silc_idlist_find_channel_by_name(server->global_list,
2069 channel_name, NULL);
2071 /* Channel really does not exist, create it */
2072 channel = silc_server_create_new_channel(server, server->id, cipher,
2073 channel_name, TRUE);
2074 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2080 /* If the channel does not have global users and is also empty it means the
2081 channel was created globally (by our router) and the client will be the
2082 channel founder and operator. */
2083 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2084 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2085 created = TRUE; /* Created globally by our router */
2088 /* Join to the channel */
2089 silc_server_command_join_channel(server, cmd, channel, client_id,
2092 silc_free(client_id);
2095 silc_server_command_free(cmd);
2098 /* Server side of command MOTD. Sends server's current "message of the
2099 day" to the client. */
2101 SILC_SERVER_CMD_FUNC(motd)
2103 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2104 SilcServer server = cmd->server;
2108 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2110 /* XXX show currently only our motd */
2112 if (server->config && server->config->motd &&
2113 server->config->motd->motd_file) {
2116 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2121 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2127 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2132 silc_server_command_free(cmd);
2135 SILC_SERVER_CMD_FUNC(umode)
2139 /* Checks that client has rights to add or remove channel modes. If any
2140 of the checks fails FALSE is returned. */
2142 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2143 SilcChannelClientEntry client,
2146 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2147 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2149 /* Check whether has rights to change anything */
2150 if (!is_op && !is_fo)
2153 /* Check whether has rights to change everything */
2157 /* We know that client is channel operator, check that they are not
2158 changing anything that requires channel founder rights. Rest of the
2159 modes are available automatically for channel operator. */
2161 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2162 if (is_op && !is_fo)
2165 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2166 if (is_op && !is_fo)
2171 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2172 if (is_op && !is_fo)
2175 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2176 if (is_op && !is_fo)
2181 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2182 if (is_op && !is_fo)
2185 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2186 if (is_op && !is_fo)
2194 /* Server side command of CMODE. Changes channel mode */
2196 SILC_SERVER_CMD_FUNC(cmode)
2198 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2199 SilcServer server = cmd->server;
2200 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2201 SilcChannelID *channel_id;
2202 SilcChannelEntry channel;
2203 SilcChannelClientEntry chl;
2204 SilcBuffer packet, cidp;
2205 unsigned char *tmp, *tmp_id, *tmp_mask;
2206 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2208 SILC_LOG_DEBUG(("Start"));
2210 argc = silc_argument_get_arg_num(cmd->args);
2212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2213 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2218 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2222 /* Get Channel ID */
2223 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2226 SILC_STATUS_ERR_NO_CHANNEL_ID);
2229 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2232 SILC_STATUS_ERR_NO_CHANNEL_ID);
2236 /* Get the channel mode mask */
2237 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2240 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2243 SILC_GET32_MSB(mode_mask, tmp_mask);
2245 /* Get channel entry */
2246 channel = silc_idlist_find_channel_by_id(server->local_list,
2249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2250 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2254 /* Check whether this client is on the channel */
2255 if (!silc_server_client_on_channel(client, channel)) {
2256 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2257 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2261 /* Get entry to the channel user list */
2262 silc_list_start(channel->user_list);
2263 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2264 if (chl->client == client)
2267 /* Check that client has rights to change any requested channel modes */
2268 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2269 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2270 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2275 * Check the modes. Modes that requires nothing special operation are
2279 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2280 /* Channel uses private keys to protect traffic. Client(s) has set the
2281 key locally they want to use, server does not know that key. */
2282 /* Nothing interesting to do here now */
2284 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2285 /* The mode is removed and we need to generate and distribute
2286 new channel key. Clients are not using private channel keys
2287 anymore after this. */
2289 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2292 /* Re-generate channel key */
2293 silc_server_create_channel_key(server, channel, 0);
2295 /* Encode channel key payload to be distributed on the channel */
2297 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2298 strlen(channel->channel_key->
2300 channel->channel_key->cipher->name,
2301 channel->key_len / 8, channel->key);
2303 /* If we are normal server then we will send it to our router. If we
2304 are router we will send it to all local servers that has clients on
2306 if (server->server_type == SILC_SERVER) {
2307 if (!server->standalone)
2308 silc_server_packet_send(server,
2309 cmd->server->router->connection,
2310 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2316 /* Send to locally connected clients on the channel */
2317 silc_server_packet_send_local_channel(server, channel,
2318 SILC_PACKET_CHANNEL_KEY, 0,
2319 packet->data, packet->len, FALSE);
2320 silc_buffer_free(packet);
2324 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2325 /* User limit is set on channel */
2326 unsigned int user_limit;
2328 /* Get user limit */
2329 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2331 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2333 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2337 SILC_GET32_MSB(user_limit, tmp);
2338 channel->mode_data.user_limit = user_limit;
2341 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2342 /* User limit mode is unset. Remove user limit */
2343 channel->mode_data.user_limit = 0;
2346 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2347 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2348 /* Passphrase has been set to channel */
2350 /* Get the passphrase */
2351 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2354 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2358 /* Save the passphrase */
2359 channel->mode_data.passphrase = strdup(tmp);
2362 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2363 /* Passphrase mode is unset. remove the passphrase */
2364 if (channel->mode_data.passphrase) {
2365 silc_free(channel->mode_data.passphrase);
2366 channel->mode_data.passphrase = NULL;
2371 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2372 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2373 /* Ban list is specified for channel */
2376 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2378 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2379 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2383 /* XXX check that channel founder is not banned */
2385 /* Save the ban list */
2386 channel->mode_data.ban_list = strdup(tmp);
2389 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2390 /* Ban mode is unset. Remove the entire ban list */
2391 if (channel->mode_data.ban_list) {
2392 silc_free(channel->mode_data.ban_list);
2393 channel->mode_data.ban_list = NULL;
2398 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2399 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2400 /* Invite list is specified for channel */
2402 /* Get invite list */
2403 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2406 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2410 /* Save the invite linst */
2411 channel->mode_data.invite_list = strdup(tmp);
2414 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2415 /* Invite list mode is unset. Remove the entire invite list */
2416 if (channel->mode_data.invite_list) {
2417 silc_free(channel->mode_data.invite_list);
2418 channel->mode_data.invite_list = NULL;
2423 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2424 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2425 /* Cipher to use protect the traffic */
2426 unsigned int key_len = 128;
2430 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2433 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2437 cp = strchr(tmp, ':');
2443 /* XXX Duplicated code, make own function for this!! */
2445 /* Delete old cipher and allocate the new one */
2446 silc_cipher_free(channel->channel_key);
2447 silc_cipher_alloc(tmp, &channel->channel_key);
2453 /* Re-generate channel key */
2454 silc_server_create_channel_key(server, channel, key_len);
2456 /* Encode channel key payload to be distributed on the channel */
2458 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2459 strlen(channel->channel_key->
2461 channel->channel_key->cipher->name,
2462 channel->key_len / 8, channel->key);
2464 /* If we are normal server then we will send it to our router. If we
2465 are router we will send it to all local servers that has clients on
2467 if (server->server_type == SILC_SERVER) {
2468 if (!server->standalone)
2469 silc_server_packet_send(server,
2470 cmd->server->router->connection,
2471 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2477 /* Send to locally connected clients on the channel */
2478 silc_server_packet_send_local_channel(server, channel,
2479 SILC_PACKET_CHANNEL_KEY, 0,
2480 packet->data, packet->len, FALSE);
2481 silc_buffer_free(packet);
2484 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2485 /* Cipher mode is unset. Remove the cipher and revert back to
2488 if (channel->mode_data.cipher) {
2489 silc_free(channel->mode_data.cipher);
2490 channel->mode_data.cipher = NULL;
2491 channel->mode_data.key_len = 0;
2494 /* Generate new cipher and key for the channel */
2496 /* XXX Duplicated code, make own function for this!! */
2498 /* Delete old cipher and allocate default one */
2499 silc_cipher_free(channel->channel_key);
2500 if (!channel->cipher)
2501 silc_cipher_alloc("twofish", &channel->channel_key);
2503 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2505 /* Re-generate channel key */
2506 silc_server_create_channel_key(server, channel, 0);
2508 /* Encode channel key payload to be distributed on the channel */
2510 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2511 strlen(channel->channel_key->
2513 channel->channel_key->cipher->name,
2514 channel->key_len / 8, channel->key);
2516 /* If we are normal server then we will send it to our router. If we
2517 are router we will send it to all local servers that has clients on
2519 if (server->server_type == SILC_SERVER) {
2520 if (!server->standalone)
2521 silc_server_packet_send(server,
2522 cmd->server->router->connection,
2523 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2529 /* Send to locally connected clients on the channel */
2530 silc_server_packet_send_local_channel(server, channel,
2531 SILC_PACKET_CHANNEL_KEY, 0,
2532 packet->data, packet->len, FALSE);
2533 silc_buffer_free(packet);
2537 /* Finally, set the mode */
2538 channel->mode = mode_mask;
2540 /* Send CMODE_CHANGE notify */
2541 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2542 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2543 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2544 cidp->data, cidp->len,
2548 /* Send command reply to sender */
2549 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2550 SILC_STATUS_OK, 0, 1,
2552 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2553 packet->data, packet->len, FALSE);
2555 silc_buffer_free(packet);
2556 silc_free(channel_id);
2559 silc_server_command_free(cmd);
2562 /* Server side of CUMODE command. Changes client's mode on a channel. */
2564 SILC_SERVER_CMD_FUNC(cumode)
2566 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2567 SilcServer server = cmd->server;
2568 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2569 SilcChannelID *channel_id;
2570 SilcClientID *client_id;
2571 SilcChannelEntry channel;
2572 SilcClientEntry target_client;
2573 SilcChannelClientEntry chl;
2574 SilcBuffer packet, idp;
2575 unsigned char *tmp_id, *tmp_mask;
2576 unsigned int target_mask, sender_mask, tmp_len;
2579 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2581 /* Get Channel ID */
2582 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2584 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2585 SILC_STATUS_ERR_NO_CHANNEL_ID);
2588 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2591 SILC_STATUS_ERR_NO_CHANNEL_ID);
2595 /* Get channel entry */
2596 channel = silc_idlist_find_channel_by_id(server->local_list,
2599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2600 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2604 /* Check whether sender is on the channel */
2605 if (!silc_server_client_on_channel(client, channel)) {
2606 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2607 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2611 /* Check that client has rights to change other's rights */
2612 silc_list_start(channel->user_list);
2613 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2614 if (chl->client == client) {
2615 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2616 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2617 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2618 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2622 sender_mask = chl->mode;
2627 /* Get the target client's channel mode mask */
2628 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2630 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2631 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2634 SILC_GET32_MSB(target_mask, tmp_mask);
2636 /* Get target Client ID */
2637 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2640 SILC_STATUS_ERR_NO_CHANNEL_ID);
2643 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2645 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2646 SILC_STATUS_ERR_NO_CHANNEL_ID);
2650 /* Get target client's entry */
2651 target_client = silc_idlist_find_client_by_id(server->local_list,
2653 if (!target_client) {
2654 /* XXX If target client is not one of mine send to primary route */
2657 /* Check whether target client is on the channel */
2658 if (!silc_server_client_on_channel(target_client, channel)) {
2659 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2660 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2664 /* Get entry to the channel user list */
2665 silc_list_start(channel->user_list);
2666 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2667 if (chl->client == target_client)
2674 /* If the target client is founder, no one else can change their mode
2676 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2677 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2678 SILC_STATUS_ERR_NOT_YOU);
2682 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2683 /* Cannot promote anyone to channel founder */
2684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2685 SILC_STATUS_ERR_NOT_YOU);
2688 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2689 if (target_client == client) {
2690 /* Remove channel founder rights from itself */
2691 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2695 SILC_STATUS_ERR_NOT_YOU);
2701 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2702 /* Promote to operator */
2703 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2704 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2708 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2709 /* Demote to normal user */
2710 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2715 /* Send notify to channel, notify only if mode was actually changed. */
2717 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2718 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2719 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2720 idp->data, idp->len,
2721 tmp_mask, 4, tmp_id, tmp_len);
2722 silc_buffer_free(idp);
2725 /* Send command reply to sender */
2726 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2727 SILC_STATUS_OK, 0, 2,
2729 3, tmp_id, tmp_len);
2730 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2731 packet->data, packet->len, FALSE);
2733 silc_buffer_free(packet);
2734 silc_free(channel_id);
2735 silc_free(client_id);
2738 silc_server_command_free(cmd);
2741 /* Server side of KICK command. Kicks client out of channel. */
2743 SILC_SERVER_CMD_FUNC(kick)
2747 SILC_SERVER_CMD_FUNC(restart)
2751 SILC_SERVER_CMD_FUNC(close)
2755 SILC_SERVER_CMD_FUNC(die)
2759 SILC_SERVER_CMD_FUNC(silcoper)
2763 /* Server side command of LEAVE. Removes client from a channel. */
2765 SILC_SERVER_CMD_FUNC(leave)
2767 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2768 SilcServer server = cmd->server;
2769 SilcSocketConnection sock = cmd->sock;
2770 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2772 SilcChannelEntry channel;
2774 unsigned int i, len;
2777 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2779 /* Get Channel ID */
2780 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2783 SILC_STATUS_ERR_NO_CHANNEL_ID);
2786 id = silc_id_payload_parse_id(tmp, len);
2788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2789 SILC_STATUS_ERR_NO_CHANNEL_ID);
2793 /* Get channel entry */
2794 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2797 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2801 /* Check whether this client is on the channel */
2802 if (!silc_server_client_on_channel(id_entry, channel)) {
2803 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2804 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2808 /* Notify routers that they should remove this client from their list
2809 of clients on the channel. */
2810 if (!server->standalone)
2811 silc_server_send_remove_channel_user(server,
2812 server->router->connection,
2813 server->server_type == SILC_ROUTER ?
2814 TRUE : FALSE, id_entry->id, id);
2816 /* Remove client from channel */
2817 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2819 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2822 /* If the channel does not exist anymore we won't send anything */
2826 /* Re-generate channel key */
2827 silc_server_create_channel_key(server, channel, 0);
2829 /* Encode channel key payload to be distributed on the channel */
2831 silc_channel_key_payload_encode(len, tmp,
2832 strlen(channel->channel_key->cipher->name),
2833 channel->channel_key->cipher->name,
2834 channel->key_len / 8, channel->key);
2836 /* If we are normal server then we will send it to our router. If we
2837 are router we will send it to all local servers that has clients on
2839 if (server->server_type == SILC_SERVER) {
2840 if (!server->standalone)
2841 silc_server_packet_send(server,
2842 cmd->server->router->connection,
2843 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2844 packet->len, FALSE);
2849 /* Send to locally connected clients on the channel */
2850 silc_server_packet_send_local_channel(server, channel,
2851 SILC_PACKET_CHANNEL_KEY, 0,
2852 packet->data, packet->len, FALSE);
2854 silc_buffer_free(packet);
2858 silc_server_command_free(cmd);
2861 /* Server side of command USERS. Resolves clients and their USERS currently
2862 joined on the requested channel. The list of Client ID's and their modes
2863 on the channel is sent back. */
2865 SILC_SERVER_CMD_FUNC(users)
2867 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2868 SilcServer server = cmd->server;
2869 SilcChannelEntry channel;
2870 SilcChannelClientEntry chl;
2873 unsigned char *channel_id;
2874 unsigned int channel_id_len;
2875 SilcBuffer client_id_list;
2876 SilcBuffer client_mode_list;
2878 unsigned char lc[4];
2879 unsigned int list_count = 0;
2880 unsigned short ident = silc_command_get_ident(cmd->payload);
2882 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
2884 /* Get Channel ID */
2885 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
2887 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2888 SILC_STATUS_ERR_NO_CHANNEL_ID);
2891 id = silc_id_payload_parse_id(channel_id, channel_id_len);
2893 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2894 SILC_STATUS_ERR_NO_CHANNEL_ID);
2898 /* If we are server and we don't know about this channel we will send
2899 the command to our router. If we know about the channel then we also
2900 have the list of users already. */
2901 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2903 if (server->server_type == SILC_SERVER && !server->standalone &&
2907 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2908 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2910 /* Send USERS command */
2911 silc_server_packet_send(server, server->router->connection,
2912 SILC_PACKET_COMMAND, cmd->packet->flags,
2913 tmpbuf->data, tmpbuf->len, TRUE);
2915 /* Reprocess this packet after received reply */
2916 silc_server_command_pending(server, SILC_COMMAND_USERS,
2917 silc_command_get_ident(cmd->payload),
2918 silc_server_command_destructor,
2919 silc_server_command_users,
2920 silc_server_command_dup(cmd));
2921 cmd->pending = TRUE;
2922 silc_command_set_ident(cmd->payload, ident);
2924 silc_buffer_free(tmpbuf);
2929 /* We are router and we will check the global list as well. */
2930 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2932 /* Channel really does not exist */
2933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2934 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2939 /* Assemble the lists now */
2941 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2942 silc_list_count(channel->user_list));
2943 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2945 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2946 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2948 silc_list_start(channel->user_list);
2949 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2951 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2952 silc_buffer_put(client_id_list, idp->data, idp->len);
2953 silc_buffer_pull(client_id_list, idp->len);
2954 silc_buffer_free(idp);
2956 /* Client's mode on channel */
2957 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2958 silc_buffer_pull(client_mode_list, 4);
2962 silc_buffer_push(client_id_list,
2963 client_id_list->data - client_id_list->head);
2964 silc_buffer_push(client_mode_list,
2965 client_mode_list->data - client_mode_list->head);
2968 SILC_PUT32_MSB(list_count, lc);
2971 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
2972 SILC_STATUS_OK, 0, 4,
2973 2, channel_id, channel_id_len,
2975 4, client_id_list->data,
2976 client_id_list->len,
2977 5, client_mode_list->data,
2978 client_mode_list->len);
2979 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2980 packet->data, packet->len, FALSE);
2982 silc_buffer_free(packet);
2983 silc_buffer_free(client_id_list);
2984 silc_buffer_free(client_mode_list);
2988 silc_server_command_free(cmd);