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(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
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_server_command_alloc();
155 ctx->server = server;
156 ctx->sock = silc_socket_dup(sock);
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);
165 silc_socket_free(ctx->sock);
169 ctx->args = silc_command_get_args(ctx->payload);
171 /* Execute command. If this fails the packet is dropped. */
172 for (cmd = silc_command_list; cmd->cb; cmd++)
173 if (cmd->cmd == silc_command_get(ctx->payload)) {
175 if (!(cmd->flags & SILC_CF_REG)) {
180 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
187 SILC_LOG_ERROR(("Unknown command, packet dropped"));
188 silc_server_command_free(ctx);
193 /* Allocate Command Context */
195 SilcServerCommandContext silc_server_command_alloc()
197 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
202 /* Free's the command context allocated before executing the command */
204 void silc_server_command_free(SilcServerCommandContext ctx)
207 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
209 if (ctx->users < 1) {
211 silc_command_free_payload(ctx->payload);
213 silc_packet_context_free(ctx->packet);
215 silc_socket_free(ctx->sock); /* Decrease reference counter */
220 /* Duplicate Command Context by adding reference counter. The context won't
221 be free'd untill it hits zero. */
223 SilcServerCommandContext
224 silc_server_command_dup(SilcServerCommandContext ctx)
227 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
232 /* Add new pending command to be executed when reply to a command has been
233 received. The `reply_cmd' is the command that will call the `callback'
234 with `context' when reply has been received. If `ident' is non-zero
235 the `callback' will be executed when received reply with command
236 identifier `ident'. */
238 void silc_server_command_pending(SilcServer server,
239 SilcCommand reply_cmd,
240 unsigned short ident,
241 SilcServerPendingDestructor destructor,
242 SilcCommandCb callback,
245 SilcServerCommandPending *reply;
247 reply = silc_calloc(1, sizeof(*reply));
248 reply->reply_cmd = reply_cmd;
249 reply->ident = ident;
250 reply->context = context;
251 reply->callback = callback;
252 reply->destructor = destructor;
253 silc_dlist_add(server->pending_commands, reply);
256 /* Deletes pending command by reply command type. */
258 void silc_server_command_pending_del(SilcServer server,
259 SilcCommand reply_cmd,
260 unsigned short ident)
262 SilcServerCommandPending *r;
264 silc_dlist_start(server->pending_commands);
265 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
266 if (r->reply_cmd == reply_cmd && r->ident == ident) {
267 silc_dlist_del(server->pending_commands, r);
273 /* Checks for pending commands and marks callbacks to be called from
274 the command reply function. Returns TRUE if there were pending command. */
276 int silc_server_command_pending_check(SilcServer server,
277 SilcServerCommandReplyContext ctx,
279 unsigned short ident)
281 SilcServerCommandPending *r;
283 silc_dlist_start(server->pending_commands);
284 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
285 if (r->reply_cmd == command && r->ident == ident) {
286 ctx->context = r->context;
287 ctx->callback = r->callback;
288 ctx->destructor = r->destructor;
297 /* Destructor function for pending callbacks. This is called when using
298 pending commands to free the context given for the pending command. */
300 static void silc_server_command_destructor(void *context)
302 silc_server_command_free((SilcServerCommandContext)context);
305 /* Sends simple status message as command reply packet */
308 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
310 SilcCommandStatus status)
314 SILC_LOG_DEBUG(("Sending command status %d", status));
316 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
317 silc_server_packet_send(cmd->server, cmd->sock,
318 SILC_PACKET_COMMAND_REPLY, 0,
319 buffer->data, buffer->len, FALSE);
320 silc_buffer_free(buffer);
323 /* Sends command status reply with one extra argument. The argument
324 type must be sent as argument. */
327 silc_server_command_send_status_data(SilcServerCommandContext cmd,
329 SilcCommandStatus status,
330 unsigned int arg_type,
332 unsigned int arg_len)
336 SILC_LOG_DEBUG(("Sending command status %d", status));
338 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
339 arg_type, arg, arg_len);
340 silc_server_packet_send(cmd->server, cmd->sock,
341 SILC_PACKET_COMMAND_REPLY, 0,
342 buffer->data, buffer->len, FALSE);
343 silc_buffer_free(buffer);
346 /******************************************************************************
350 ******************************************************************************/
353 silc_server_command_whois_parse(SilcServerCommandContext cmd,
354 SilcClientID ***client_id,
355 unsigned int *client_id_count,
363 unsigned int argc = silc_argument_get_arg_num(cmd->args);
366 /* If client ID is in the command it must be used instead of nickname */
367 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
369 /* No ID, get the nickname@server string and parse it. */
370 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
372 if (strchr(tmp, '@')) {
373 len = strcspn(tmp, "@");
374 *nickname = silc_calloc(len + 1, sizeof(char));
375 memcpy(*nickname, tmp, len);
376 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
377 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
379 *nickname = strdup(tmp);
382 silc_server_command_send_status_reply(cmd, command,
383 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
387 /* Command includes ID, we must use that. Also check whether the command
388 has more than one ID set - take them all. */
390 *client_id = silc_calloc(1, sizeof(**client_id));
391 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
392 if ((*client_id)[0] == NULL) {
393 silc_free(*client_id);
396 *client_id_count = 1;
398 /* Take all ID's from the command packet */
400 for (k = 1, i = 4; i < argc + 1; i++) {
401 tmp = silc_argument_get_arg_type(cmd->args, i, &len);
403 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
404 (*client_id_count + 1));
405 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
406 if ((*client_id)[k] == NULL) {
407 /* Cleanup all and fail */
408 for (i = 0; i < *client_id_count; i++)
409 silc_free((*client_id)[i]);
410 silc_free(*client_id);
413 (*client_id_count)++;
419 /* Command includes ID, use that */
422 /* Get the max count of reply messages allowed */
423 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
433 silc_server_command_whois_check(SilcServerCommandContext cmd,
434 SilcClientEntry *clients,
435 unsigned int clients_count)
437 SilcServer server = cmd->server;
439 SilcClientEntry entry;
441 for (i = 0; i < clients_count; i++) {
444 if (!entry->nickname || !entry->username) {
446 unsigned short old_ident;
451 old_ident = silc_command_get_ident(cmd->payload);
452 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
453 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
455 /* Send WHOIS command */
456 silc_server_packet_send(server, entry->router->connection,
457 SILC_PACKET_COMMAND, cmd->packet->flags,
458 tmpbuf->data, tmpbuf->len, TRUE);
460 /* Reprocess this packet after received reply */
461 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
462 silc_command_get_ident(cmd->payload),
463 silc_server_command_destructor,
464 silc_server_command_whois,
465 silc_server_command_dup(cmd));
468 silc_command_set_ident(cmd->payload, old_ident);
470 silc_buffer_free(tmpbuf);
479 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
480 SilcClientEntry *clients,
481 unsigned int clients_count)
483 SilcServer server = cmd->server;
485 int i, count = 0, len;
486 SilcBuffer packet, idp;
487 SilcClientEntry entry;
488 SilcCommandStatus status;
489 unsigned short ident = silc_command_get_ident(cmd->payload);
491 status = SILC_STATUS_OK;
492 if (clients_count > 1)
493 status = SILC_STATUS_LIST_START;
495 for (i = 0; i < clients_count; i++) {
498 if (count && i - 1 == count)
501 if (clients_count > 2)
502 status = SILC_STATUS_LIST_ITEM;
504 if (clients_count > 1 && i == clients_count - 1)
505 status = SILC_STATUS_LIST_END;
507 /* Sanity check, however these should never fail. However, as
508 this sanity check has been added here they have failed. */
509 if (!entry->nickname || !entry->username)
512 /* Send WHOIS reply */
513 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
514 tmp = silc_argument_get_first_arg(cmd->args, NULL);
518 char nh[256], uh[256];
519 unsigned char idle[4];
520 SilcSocketConnection hsock;
522 memset(uh, 0, sizeof(uh));
523 memset(nh, 0, sizeof(nh));
525 strncat(nh, entry->nickname, strlen(entry->nickname));
526 if (!strchr(entry->nickname, '@')) {
528 len = entry->router ? strlen(entry->router->server_name) :
529 strlen(server->server_name);
530 strncat(nh, entry->router ? entry->router->server_name :
531 server->server_name, len);
534 strncat(uh, entry->username, strlen(entry->username));
535 if (!strchr(entry->username, '@')) {
537 hsock = (SilcSocketConnection)entry->connection;
538 len = strlen(hsock->hostname);
539 strncat(uh, hsock->hostname, len);
542 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
545 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
547 2, idp->data, idp->len,
551 strlen(entry->userinfo),
555 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
556 0, packet->data, packet->len, FALSE);
558 silc_buffer_free(packet);
559 silc_buffer_free(idp);
564 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
566 SilcServer server = cmd->server;
567 char *nick = NULL, *server_name = NULL;
568 int count = 0, clients_count = 0;
569 SilcClientEntry *clients = NULL, entry;
570 SilcClientID **client_id = NULL;
571 unsigned int client_id_count = 0;
574 /* Protocol dictates that we must always send the received WHOIS request
575 to our router if we are normal server, so let's do it now unless we
576 are standalone. We will not send any replies to the client until we
577 have received reply from the router. */
578 if (server->server_type == SILC_SERVER &&
579 !cmd->pending && !server->standalone) {
581 unsigned short old_ident;
583 old_ident = silc_command_get_ident(cmd->payload);
584 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
585 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
587 /* Send WHOIS command to our router */
588 silc_server_packet_send(server, (SilcSocketConnection)
589 server->router->connection,
590 SILC_PACKET_COMMAND, cmd->packet->flags,
591 tmpbuf->data, tmpbuf->len, TRUE);
593 /* Reprocess this packet after received reply from router */
594 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
595 silc_command_get_ident(cmd->payload),
596 silc_server_command_destructor,
597 silc_server_command_whois,
598 silc_server_command_dup(cmd));
601 silc_command_set_ident(cmd->payload, old_ident);
603 silc_buffer_free(tmpbuf);
608 /* We are ready to process the command request. Let's search for the
609 requested client and send reply to the requesting client. */
611 /* Parse the whois request */
612 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
613 &nick, &server_name, &count,
617 /* Get all clients matching that ID or nickname from local list */
618 if (client_id_count) {
619 /* Check all Client ID's received in the command packet */
620 for (i = 0; i < client_id_count; i++) {
621 entry = silc_idlist_find_client_by_id(server->local_list,
624 clients = silc_realloc(clients, sizeof(*clients) *
625 (clients_count + 1));
626 clients[clients_count++] = entry;
630 clients = silc_idlist_get_clients_by_nickname(server->local_list,
635 /* Check global list as well */
637 if (client_id_count) {
638 /* Check all Client ID's received in the command packet */
639 for (i = 0; i < client_id_count; i++) {
640 entry = silc_idlist_find_client_by_id(server->global_list,
643 clients = silc_realloc(clients, sizeof(*clients) *
644 (clients_count + 1));
645 clients[clients_count++] = entry;
649 clients = silc_idlist_get_clients_by_nickname(server->global_list,
656 /* Such client(s) really does not exist in the SILC network. */
657 if (!client_id_count) {
658 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
659 SILC_STATUS_ERR_NO_SUCH_NICK,
660 3, nick, strlen(nick));
662 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
663 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
664 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
665 2, idp->data, idp->len);
666 silc_buffer_free(idp);
671 /* Router always finds the client entry if it exists in the SILC network.
672 However, it might be incomplete entry and does not include all the
673 mandatory fields that WHOIS command reply requires. Check for these and
674 make query from the server who owns the client if some fields are
676 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
681 /* Send the command reply to the client */
682 silc_server_command_whois_send_reply(cmd, clients, clients_count);
685 if (client_id_count) {
686 for (i = 0; i < client_id_count; i++)
687 silc_free(client_id[i]);
688 silc_free(client_id);
695 silc_free(server_name);
701 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
703 SilcServer server = cmd->server;
704 char *nick = NULL, *server_name = NULL;
705 int count = 0, clients_count = 0;
706 SilcClientEntry *clients = NULL, entry;
707 SilcClientID **client_id = NULL;
708 unsigned int client_id_count = 0;
711 /* Parse the whois request */
712 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
713 &nick, &server_name, &count,
717 /* Process the command request. Let's search for the requested client and
718 send reply to the requesting server. */
720 if (client_id_count) {
721 /* Check all Client ID's received in the command packet */
722 for (i = 0; i < client_id_count; i++) {
723 entry = silc_idlist_find_client_by_id(server->local_list,
726 clients = silc_realloc(clients, sizeof(*clients) *
727 (clients_count + 1));
728 clients[clients_count++] = entry;
732 clients = silc_idlist_get_clients_by_nickname(server->local_list,
736 clients = silc_idlist_get_clients_by_hash(server->local_list,
737 nick, server->md5hash,
741 /* If we are router we will check our global list as well. */
742 if (!clients && server->server_type == SILC_ROUTER) {
743 if (client_id_count) {
744 /* Check all Client ID's received in the command packet */
745 for (i = 0; i < client_id_count; i++) {
746 entry = silc_idlist_find_client_by_id(server->global_list,
749 clients = silc_realloc(clients, sizeof(*clients) *
750 (clients_count + 1));
751 clients[clients_count++] = entry;
755 clients = silc_idlist_get_clients_by_nickname(server->global_list,
759 clients = silc_idlist_get_clients_by_hash(server->global_list,
760 nick, server->md5hash,
766 /* Such a client really does not exist in the SILC network. */
767 if (!client_id_count) {
768 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
769 SILC_STATUS_ERR_NO_SUCH_NICK,
770 3, nick, strlen(nick));
772 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
773 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
774 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
775 2, idp->data, idp->len);
776 silc_buffer_free(idp);
781 /* Router always finds the client entry if it exists in the SILC network.
782 However, it might be incomplete entry and does not include all the
783 mandatory fields that WHOIS command reply requires. Check for these and
784 make query from the server who owns the client if some fields are
786 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
791 /* Send the command reply to the client */
792 silc_server_command_whois_send_reply(cmd, clients, clients_count);
795 if (client_id_count) {
796 for (i = 0; i < client_id_count; i++)
797 silc_free(client_id[i]);
798 silc_free(client_id);
805 silc_free(server_name);
810 /* Server side of command WHOIS. Processes user's query and sends found
811 results as command replies back to the client. */
813 SILC_SERVER_CMD_FUNC(whois)
815 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
818 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
820 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
821 ret = silc_server_command_whois_from_client(cmd);
822 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
823 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
824 ret = silc_server_command_whois_from_server(cmd);
827 silc_server_command_free(cmd);
830 SILC_SERVER_CMD_FUNC(whowas)
834 /******************************************************************************
838 ******************************************************************************/
840 /* Checks that all mandatory fields are present. If not then send WHOIS
841 request to the server who owns the client. We use WHOIS because we want
842 to get as much information as possible at once. */
845 silc_server_command_identify_check(SilcServerCommandContext cmd,
846 SilcClientEntry *clients,
847 unsigned int clients_count)
849 SilcServer server = cmd->server;
851 SilcClientEntry entry;
853 for (i = 0; i < clients_count; i++) {
856 if (!entry->nickname) {
858 unsigned short old_ident;
863 old_ident = silc_command_get_ident(cmd->payload);
864 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
865 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
866 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
868 /* Send WHOIS request. We send WHOIS since we're doing the requesting
869 now anyway so make it a good one. */
870 silc_server_packet_send(server, entry->router->connection,
871 SILC_PACKET_COMMAND, cmd->packet->flags,
872 tmpbuf->data, tmpbuf->len, TRUE);
874 /* Reprocess this packet after received reply */
875 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
876 silc_command_get_ident(cmd->payload),
877 silc_server_command_destructor,
878 silc_server_command_identify,
879 silc_server_command_dup(cmd));
883 /* Put old data back to the Command Payload we just changed */
884 silc_command_set_ident(cmd->payload, old_ident);
885 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
887 silc_buffer_free(tmpbuf);
896 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
897 SilcClientEntry *clients,
898 unsigned int clients_count)
900 SilcServer server = cmd->server;
902 int i, count = 0, len;
903 SilcBuffer packet, idp;
904 SilcClientEntry entry;
905 SilcCommandStatus status;
906 unsigned short ident = silc_command_get_ident(cmd->payload);
908 status = SILC_STATUS_OK;
909 if (clients_count > 1)
910 status = SILC_STATUS_LIST_START;
912 for (i = 0; i < clients_count; i++) {
915 if (count && i - 1 == count)
918 if (clients_count > 2)
919 status = SILC_STATUS_LIST_ITEM;
921 if (clients_count > 1 && i == clients_count - 1)
922 status = SILC_STATUS_LIST_END;
924 /* Send IDENTIFY reply */
925 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
926 tmp = silc_argument_get_first_arg(cmd->args, NULL);
930 char nh[256], uh[256];
931 SilcSocketConnection hsock;
933 memset(uh, 0, sizeof(uh));
934 memset(nh, 0, sizeof(nh));
936 strncat(nh, entry->nickname, strlen(entry->nickname));
937 if (!strchr(entry->nickname, '@')) {
939 len = entry->router ? strlen(entry->router->server_name) :
940 strlen(server->server_name);
941 strncat(nh, entry->router ? entry->router->server_name :
942 server->server_name, len);
945 if (!entry->username) {
946 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
947 SILC_STATUS_OK, ident, 2,
948 2, idp->data, idp->len,
951 strncat(uh, entry->username, strlen(entry->username));
952 if (!strchr(entry->username, '@')) {
954 hsock = (SilcSocketConnection)entry->connection;
955 len = strlen(hsock->hostname);
956 strncat(uh, hsock->hostname, len);
959 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
960 SILC_STATUS_OK, ident, 3,
961 2, idp->data, idp->len,
966 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
967 0, packet->data, packet->len, FALSE);
969 silc_buffer_free(packet);
970 silc_buffer_free(idp);
976 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
978 SilcServer server = cmd->server;
979 char *nick = NULL, *server_name = NULL;
980 int count = 0, clients_count = 0;
981 SilcClientEntry *clients = NULL, entry;
982 SilcClientID **client_id = NULL;
983 unsigned int client_id_count = 0;
986 /* Protocol dictates that we must always send the received IDENTIFY request
987 to our router if we are normal server, so let's do it now unless we
988 are standalone. We will not send any replies to the client until we
989 have received reply from the router. */
990 if (server->server_type == SILC_SERVER &&
991 !cmd->pending && !server->standalone) {
993 unsigned short old_ident;
995 old_ident = silc_command_get_ident(cmd->payload);
996 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
997 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
999 /* Send IDENTIFY command to our router */
1000 silc_server_packet_send(server, (SilcSocketConnection)
1001 server->router->connection,
1002 SILC_PACKET_COMMAND, cmd->packet->flags,
1003 tmpbuf->data, tmpbuf->len, TRUE);
1005 /* Reprocess this packet after received reply from router */
1006 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1007 silc_command_get_ident(cmd->payload),
1008 silc_server_command_destructor,
1009 silc_server_command_identify,
1010 silc_server_command_dup(cmd));
1011 cmd->pending = TRUE;
1013 silc_command_set_ident(cmd->payload, old_ident);
1015 silc_buffer_free(tmpbuf);
1020 /* We are ready to process the command request. Let's search for the
1021 requested client and send reply to the requesting client. */
1023 /* Parse the IDENTIFY request */
1024 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1025 &nick, &server_name, &count,
1026 SILC_COMMAND_IDENTIFY))
1029 /* Get all clients matching that ID or nickname from local list */
1030 if (client_id_count) {
1031 /* Check all Client ID's received in the command packet */
1032 for (i = 0; i < client_id_count; i++) {
1033 entry = silc_idlist_find_client_by_id(server->local_list,
1034 client_id[i], NULL);
1036 clients = silc_realloc(clients, sizeof(*clients) *
1037 (clients_count + 1));
1038 clients[clients_count++] = entry;
1042 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1047 /* Check global list as well */
1049 if (client_id_count) {
1050 /* Check all Client ID's received in the command packet */
1051 for (i = 0; i < client_id_count; i++) {
1052 entry = silc_idlist_find_client_by_id(server->global_list,
1053 client_id[i], NULL);
1055 clients = silc_realloc(clients, sizeof(*clients) *
1056 (clients_count + 1));
1057 clients[clients_count++] = entry;
1061 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1068 /* Such a client really does not exist in the SILC network. */
1069 if (!client_id_count) {
1070 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1071 SILC_STATUS_ERR_NO_SUCH_NICK,
1072 3, nick, strlen(nick));
1074 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1075 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1076 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1077 2, idp->data, idp->len);
1078 silc_buffer_free(idp);
1083 /* Check that all mandatory fields are present and request those data
1084 from the server who owns the client if necessary. */
1085 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1090 /* Send the command reply to the client */
1091 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1094 if (client_id_count) {
1095 for (i = 0; i < client_id_count; i++)
1096 silc_free(client_id[i]);
1097 silc_free(client_id);
1104 silc_free(server_name);
1110 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1112 SilcServer server = cmd->server;
1113 char *nick = NULL, *server_name = NULL;
1114 int count = 0, clients_count = 0;
1115 SilcClientEntry *clients = NULL, entry;
1116 SilcClientID **client_id = NULL;
1117 unsigned int client_id_count = 0;
1120 /* Parse the IDENTIFY request */
1121 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1122 &nick, &server_name, &count,
1123 SILC_COMMAND_IDENTIFY))
1126 /* Process the command request. Let's search for the requested client and
1127 send reply to the requesting server. */
1129 if (client_id_count) {
1130 /* Check all Client ID's received in the command packet */
1131 for (i = 0; i < client_id_count; i++) {
1132 entry = silc_idlist_find_client_by_id(server->local_list,
1133 client_id[i], NULL);
1135 clients = silc_realloc(clients, sizeof(*clients) *
1136 (clients_count + 1));
1137 clients[clients_count++] = entry;
1141 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1145 clients = silc_idlist_get_clients_by_hash(server->local_list,
1146 nick, server->md5hash,
1150 /* If we are router we will check our global list as well. */
1151 if (!clients && server->server_type == SILC_ROUTER) {
1152 if (client_id_count) {
1153 /* Check all Client ID's received in the command packet */
1154 for (i = 0; i < client_id_count; i++) {
1155 entry = silc_idlist_find_client_by_id(server->global_list,
1156 client_id[i], NULL);
1158 clients = silc_realloc(clients, sizeof(*clients) *
1159 (clients_count + 1));
1160 clients[clients_count++] = entry;
1164 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1168 clients = silc_idlist_get_clients_by_hash(server->global_list,
1169 nick, server->md5hash,
1175 /* Such a client really does not exist in the SILC network. */
1176 if (!client_id_count) {
1177 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1178 SILC_STATUS_ERR_NO_SUCH_NICK,
1179 3, nick, strlen(nick));
1181 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1182 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1183 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1184 2, idp->data, idp->len);
1185 silc_buffer_free(idp);
1190 /* Check that all mandatory fields are present and request those data
1191 from the server who owns the client if necessary. */
1192 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1197 /* Send the command reply */
1198 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1201 if (client_id_count) {
1202 for (i = 0; i < client_id_count; i++)
1203 silc_free(client_id[i]);
1204 silc_free(client_id);
1211 silc_free(server_name);
1216 SILC_SERVER_CMD_FUNC(identify)
1218 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1221 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1223 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1224 ret = silc_server_command_identify_from_client(cmd);
1225 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1226 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1227 ret = silc_server_command_identify_from_server(cmd);
1230 silc_server_command_free(cmd);
1233 /* Checks string for bad characters and returns TRUE if they are found. */
1235 static int silc_server_command_bad_chars(char *nick)
1237 if (strchr(nick, '\\')) return TRUE;
1238 if (strchr(nick, '\"')) return TRUE;
1239 if (strchr(nick, '´')) return TRUE;
1240 if (strchr(nick, '`')) return TRUE;
1241 if (strchr(nick, '\'')) return TRUE;
1242 if (strchr(nick, '*')) return TRUE;
1243 if (strchr(nick, '/')) return TRUE;
1244 if (strchr(nick, '@')) return TRUE;
1249 /* Server side of command NICK. Sets nickname for user. Setting
1250 nickname causes generation of a new client ID for the client. The
1251 new client ID is sent to the client after changing the nickname. */
1253 SILC_SERVER_CMD_FUNC(nick)
1255 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1256 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1257 SilcServer server = cmd->server;
1258 SilcBuffer packet, nidp, oidp;
1259 SilcClientID *new_id;
1262 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1264 /* Check nickname */
1265 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1266 if (silc_server_command_bad_chars(nick) == TRUE) {
1267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1268 SILC_STATUS_ERR_BAD_NICKNAME);
1272 /* Create new Client ID */
1273 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1274 cmd->server->md5hash, nick,
1277 /* Send notify about nickname change to our router. We send the new
1278 ID and ask to replace it with the old one. If we are router the
1279 packet is broadcasted. Send NICK_CHANGE notify. */
1280 if (!server->standalone)
1281 silc_server_send_notify_nick_change(server, server->router->connection,
1282 server->server_type == SILC_SERVER ?
1283 FALSE : TRUE, client->id,
1284 new_id, SILC_ID_CLIENT_LEN);
1286 /* Remove old cache entry */
1287 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1290 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1294 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1295 silc_free(client->id);
1298 /* Save the nickname as this client is our local client */
1299 if (client->nickname)
1300 silc_free(client->nickname);
1302 client->nickname = strdup(nick);
1303 client->id = new_id;
1305 /* Update client cache */
1306 silc_idcache_add(server->local_list->clients, client->nickname,
1307 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1309 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1311 /* Send NICK_CHANGE notify to the client's channels */
1312 silc_server_send_notify_on_channels(server, client,
1313 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1314 oidp->data, oidp->len,
1315 nidp->data, nidp->len);
1317 /* Send the new Client ID as reply command back to client */
1318 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1319 SILC_STATUS_OK, 0, 1,
1320 2, nidp->data, nidp->len);
1321 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1322 0, packet->data, packet->len, FALSE);
1324 silc_buffer_free(packet);
1325 silc_buffer_free(nidp);
1326 silc_buffer_free(oidp);
1329 silc_server_command_free(cmd);
1332 SILC_SERVER_CMD_FUNC(list)
1336 /* Server side of TOPIC command. Sets topic for channel and/or returns
1337 current topic to client. */
1339 SILC_SERVER_CMD_FUNC(topic)
1341 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1342 SilcServer server = cmd->server;
1343 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1344 SilcChannelID *channel_id;
1345 SilcChannelEntry channel;
1346 SilcChannelClientEntry chl;
1347 SilcBuffer packet, idp;
1349 unsigned int argc, tmp_len;
1351 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1353 argc = silc_argument_get_arg_num(cmd->args);
1355 /* Get Channel ID */
1356 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1358 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1359 SILC_STATUS_ERR_NO_CHANNEL_ID);
1362 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1364 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1365 SILC_STATUS_ERR_NO_CHANNEL_ID);
1369 /* Check whether the channel exists */
1370 channel = silc_idlist_find_channel_by_id(server->local_list,
1373 channel = silc_idlist_find_channel_by_id(server->global_list,
1376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1377 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1384 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1387 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1391 if (strlen(tmp) > 256) {
1392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1393 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1397 /* See whether has rights to change topic */
1398 silc_list_start(channel->user_list);
1399 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1400 if (chl->client == client)
1403 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1404 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1406 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1411 /* Set the topic for channel */
1413 silc_free(channel->topic);
1414 channel->topic = strdup(tmp);
1416 /* Send TOPIC_SET notify type to the network */
1417 if (!server->standalone)
1418 silc_server_send_notify_topic_set(server, server->router->connection,
1419 server->server_type == SILC_ROUTER ?
1420 TRUE : FALSE, channel, client->id,
1421 SILC_ID_CLIENT_LEN, channel->topic);
1423 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1425 /* Send notify about topic change to all clients on the channel */
1426 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1427 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1428 idp->data, idp->len,
1429 channel->topic, strlen(channel->topic));
1430 silc_buffer_free(idp);
1433 /* Send the topic to client as reply packet */
1434 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1436 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1437 SILC_STATUS_OK, 0, 2,
1438 2, idp->data, idp->len,
1440 strlen(channel->topic));
1442 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1443 SILC_STATUS_OK, 0, 1,
1444 2, idp->data, idp->len);
1445 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1446 0, packet->data, packet->len, FALSE);
1448 silc_buffer_free(packet);
1449 silc_buffer_free(idp);
1450 silc_free(channel_id);
1453 silc_server_command_free(cmd);
1456 /* Server side of INVITE command. Invites some client to join some channel. */
1458 SILC_SERVER_CMD_FUNC(invite)
1460 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1461 SilcServer server = cmd->server;
1462 SilcSocketConnection sock = cmd->sock, dest_sock;
1463 SilcClientEntry sender, dest;
1464 SilcClientID *dest_id;
1465 SilcChannelEntry channel;
1466 SilcChannelID *channel_id;
1471 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1473 /* Get destination ID */
1474 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1477 SILC_STATUS_ERR_NO_CLIENT_ID);
1480 dest_id = silc_id_payload_parse_id(tmp, len);
1482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1483 SILC_STATUS_ERR_NO_CLIENT_ID);
1487 /* Get Channel ID */
1488 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1490 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1491 SILC_STATUS_ERR_NO_CHANNEL_ID);
1494 channel_id = silc_id_payload_parse_id(tmp, len);
1496 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1497 SILC_STATUS_ERR_NO_CHANNEL_ID);
1501 /* Check whether the channel exists */
1502 channel = silc_idlist_find_channel_by_id(server->local_list,
1505 channel = silc_idlist_find_channel_by_id(server->global_list,
1508 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1509 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1514 /* Check whether the sender of this command is on the channel. */
1515 sender = (SilcClientEntry)sock->user_data;
1516 if (!silc_server_client_on_channel(sender, channel)) {
1517 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1518 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1522 /* Check whether the channel is invite-only channel. If yes then the
1523 sender of this command must be at least channel operator. */
1524 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1525 SilcChannelClientEntry chl;
1527 silc_list_start(channel->user_list);
1528 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1529 if (chl->client == sender) {
1530 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1532 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1539 /* Find the connection data for the destination. If it is local we will
1540 send it directly otherwise we will send it to router for routing. */
1541 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1543 dest_sock = (SilcSocketConnection)dest->connection;
1545 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1547 /* Check whether the requested client is already on the channel. */
1548 /* XXX if we are normal server we don't know about global clients on
1549 the channel thus we must request it (USERS command), check from
1550 local cache as well. */
1551 if (silc_server_client_on_channel(dest, channel)) {
1552 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1553 SILC_STATUS_ERR_USER_ON_CHANNEL);
1557 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1559 /* Send notify to the client that is invited to the channel */
1560 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1562 SILC_NOTIFY_TYPE_INVITE, 2,
1563 sidp->data, sidp->len, tmp, len);
1565 /* Send command reply */
1566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1569 silc_buffer_free(sidp);
1572 silc_server_command_free(cmd);
1577 SilcSocketConnection sock;
1581 /* Quits connection to client. This gets called if client won't
1582 close the connection even when it has issued QUIT command. */
1584 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1586 QuitInternal q = (QuitInternal)context;
1588 /* Free all client specific data, such as client entry and entires
1589 on channels this client may be on. */
1590 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1592 q->sock->user_data = NULL;
1594 /* Close the connection on our side */
1595 silc_server_close_connection(q->server, q->sock);
1597 silc_free(q->signoff);
1601 /* Quits SILC session. This is the normal way to disconnect client. */
1603 SILC_SERVER_CMD_FUNC(quit)
1605 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1606 SilcServer server = cmd->server;
1607 SilcSocketConnection sock = cmd->sock;
1609 unsigned char *tmp = NULL;
1610 unsigned int len = 0;
1612 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
1614 /* Get destination ID */
1615 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1619 q = silc_calloc(1, sizeof(*q));
1622 q->signoff = tmp ? strdup(tmp) : NULL;
1624 /* We quit the connection with little timeout */
1625 silc_task_register(server->timeout_queue, sock->sock,
1626 silc_server_command_quit_cb, (void *)q,
1627 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1629 silc_server_command_free(cmd);
1632 SILC_SERVER_CMD_FUNC(kill)
1636 /* Server side of command INFO. This sends information about us to
1637 the client. If client requested specific server we will send the
1638 command to that server. */
1640 SILC_SERVER_CMD_FUNC(info)
1642 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1643 SilcServer server = cmd->server;
1644 SilcBuffer packet, idp;
1645 char info_string[256], *dest_server;
1647 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1649 /* Get server name */
1650 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1653 SILC_STATUS_ERR_NO_SUCH_SERVER);
1657 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1658 /* Send our reply */
1659 memset(info_string, 0, sizeof(info_string));
1660 snprintf(info_string, sizeof(info_string),
1661 "location: %s server: %s admin: %s <%s>",
1662 server->config->admin_info->location,
1663 server->config->admin_info->server_type,
1664 server->config->admin_info->admin_name,
1665 server->config->admin_info->admin_email);
1667 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1669 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1670 SILC_STATUS_OK, 0, 2,
1671 2, idp->data, idp->len,
1673 strlen(info_string));
1674 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1675 packet->data, packet->len, FALSE);
1677 silc_buffer_free(packet);
1678 silc_buffer_free(idp);
1680 /* Send this command to the requested server */
1682 if (server->server_type == SILC_SERVER && !server->standalone) {
1686 if (server->server_type == SILC_ROUTER) {
1692 silc_server_command_free(cmd);
1695 /* Server side of command PING. This just replies to the ping. */
1697 SILC_SERVER_CMD_FUNC(ping)
1699 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1700 SilcServer server = cmd->server;
1705 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1708 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1710 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1711 SILC_STATUS_ERR_NO_SERVER_ID);
1714 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1718 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1719 /* Send our reply */
1720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1723 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1724 SILC_STATUS_ERR_NO_SUCH_SERVER);
1731 silc_server_command_free(cmd);
1734 /* Assembles USERS command and executes it. This is called when client
1735 joins to a channel and we wan't to send USERS command reply to the
1738 void silc_server_command_send_users(SilcServer server,
1739 SilcSocketConnection sock,
1740 SilcChannelEntry channel,
1743 SilcServerCommandContext cmd;
1744 SilcBuffer buffer, idp;
1745 SilcPacketContext *packet = silc_packet_context_alloc();
1747 SILC_LOG_DEBUG(("Start"));
1749 /* Create USERS command packet and process it. */
1750 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1751 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1752 1, idp->data, idp->len);
1754 packet->buffer = silc_buffer_copy(buffer);
1755 packet->sock = sock;
1756 packet->type = SILC_PACKET_COMMAND;
1758 cmd = silc_server_command_alloc();
1759 cmd->payload = silc_command_payload_parse(buffer);
1760 if (!cmd->payload) {
1762 silc_buffer_free(buffer);
1763 silc_buffer_free(idp);
1764 silc_packet_context_free(packet);
1767 cmd->args = silc_command_get_args(cmd->payload);
1768 cmd->server = server;
1769 cmd->sock = silc_socket_dup(sock);
1770 cmd->packet = silc_packet_context_dup(packet);
1771 cmd->pending = FALSE;
1774 /* If this function was called from pending command then instead of
1775 processing the command now, register a pending command callback which
1776 will process it after we've received the automatic USERS command
1777 reply which server will send in JOIN. */
1778 silc_server_command_pending(server, SILC_COMMAND_USERS, 0, NULL,
1779 silc_server_command_users, cmd);
1780 cmd->pending = TRUE;
1781 silc_buffer_free(buffer);
1782 silc_buffer_free(idp);
1786 /* Process USERS command. */
1787 silc_server_command_users((void *)cmd);
1789 silc_buffer_free(buffer);
1790 silc_buffer_free(idp);
1791 silc_packet_context_free(packet);
1794 /* Internal routine to join channel. The channel sent to this function
1795 has been either created or resolved from ID lists. This joins the sent
1796 client to the channel. */
1798 static void silc_server_command_join_channel(SilcServer server,
1799 SilcServerCommandContext cmd,
1800 SilcChannelEntry channel,
1801 SilcClientID *client_id,
1805 SilcSocketConnection sock = cmd->sock;
1807 unsigned int tmp_len;
1808 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1809 SilcClientEntry client;
1810 SilcChannelClientEntry chl;
1811 SilcBuffer reply, chidp, clidp, keyp;
1812 unsigned short ident = silc_command_get_ident(cmd->payload);
1814 SILC_LOG_DEBUG(("Start"));
1819 /* Get passphrase */
1820 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1822 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1823 memcpy(passphrase, tmp, tmp_len);
1827 * Check channel modes
1830 /* Check invite list if channel is invite-only channel */
1831 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1832 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1833 /* Invite list is specified. Check whether client is invited in the
1834 list. If not, then check whether it has been invited otherwise. */
1837 /* XXX client must be invited to be able to join the channel */
1841 /* Check ban list if set */
1842 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1846 /* Check the channel passphrase if set. */
1847 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1848 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1849 strlen(channel->mode_data.passphrase))) {
1850 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1851 SILC_STATUS_ERR_BAD_PASSWORD);
1856 /* Check user count limit if set. */
1857 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1858 if (silc_list_count(channel->user_list) + 1 >
1859 channel->mode_data.user_limit) {
1860 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1861 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1867 * Client is allowed to join to the channel. Make it happen.
1870 /* Get the client entry */
1871 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1872 client = (SilcClientEntry)sock->user_data;
1874 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1877 /* XXX actually this is useless since router finds always cell's
1878 local clients from its local lists. */
1879 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1886 /* Check whether the client already is on the channel */
1887 if (silc_server_client_on_channel(client, channel)) {
1888 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1889 SILC_STATUS_ERR_USER_ON_CHANNEL);
1893 /* Generate new channel key as protocol dictates */
1894 if ((!created && silc_list_count(channel->user_list) > 0) ||
1895 !channel->channel_key)
1896 silc_server_create_channel_key(server, channel, 0);
1898 /* Send the channel key. This is broadcasted to the channel but is not
1899 sent to the client who is joining to the channel. */
1900 silc_server_send_channel_key(server, NULL, channel,
1901 server->server_type == SILC_ROUTER ?
1902 FALSE : !server->standalone);
1904 /* Join the client to the channel by adding it to channel's user list.
1905 Add also the channel to client entry's channels list for fast cross-
1907 chl = silc_calloc(1, sizeof(*chl));
1909 chl->client = client;
1910 chl->channel = channel;
1911 silc_list_add(channel->user_list, chl);
1912 silc_list_add(client->channels, chl);
1914 /* Encode Client ID Payload of the original client who wants to join */
1915 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1917 /* Encode command reply packet */
1918 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1919 SILC_PUT32_MSB(channel->mode, mode);
1920 SILC_PUT32_MSB(created, tmp2);
1921 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1922 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1923 strlen(channel->channel_key->
1925 channel->channel_key->cipher->name,
1926 channel->key_len / 8, channel->key);
1928 if (!channel->topic) {
1930 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1931 SILC_STATUS_OK, ident, 5,
1932 2, channel->channel_name,
1933 strlen(channel->channel_name),
1934 3, chidp->data, chidp->len,
1937 6, keyp->data, keyp->len);
1940 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1941 SILC_STATUS_OK, ident, 6,
1942 2, channel->channel_name,
1943 strlen(channel->channel_name),
1944 3, chidp->data, chidp->len,
1947 6, keyp->data, keyp->len,
1949 strlen(channel->topic));
1952 /* Send command reply */
1953 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1954 reply->data, reply->len, FALSE);
1956 if (!cmd->pending) {
1957 /* Send JOIN notify to locally connected clients on the channel */
1958 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1959 SILC_NOTIFY_TYPE_JOIN, 2,
1960 clidp->data, clidp->len,
1961 chidp->data, chidp->len);
1963 /* Send JOIN notify packet to our primary router */
1964 if (!server->standalone)
1965 silc_server_send_notify_join(server, server->router->connection,
1966 server->server_type == SILC_ROUTER ?
1967 TRUE : FALSE, channel, client->id,
1968 SILC_ID_CLIENT_LEN);
1971 /* Send USERS command reply to the joined channel so the user sees who
1972 is currently on the channel. */
1973 silc_server_command_send_users(server, sock, channel, cmd->pending);
1975 silc_buffer_free(reply);
1976 silc_buffer_free(clidp);
1977 silc_buffer_free(chidp);
1978 silc_buffer_free(keyp);
1982 silc_free(passphrase);
1985 /* Server side of command JOIN. Joins client into requested channel. If
1986 the channel does not exist it will be created. */
1988 SILC_SERVER_CMD_FUNC(join)
1990 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1991 SilcServer server = cmd->server;
1993 char *tmp, *channel_name = NULL, *cipher, *hmac;
1994 SilcChannelEntry channel;
1995 unsigned int umode = 0;
1996 int created = FALSE;
1997 SilcClientID *client_id;
1999 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2001 /* Get channel name */
2002 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2005 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2010 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2011 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2012 SILC_STATUS_ERR_BAD_CHANNEL);
2013 silc_free(channel_name);
2017 /* Get Client ID of the client who is joining to the channel */
2018 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2021 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2024 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2026 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2027 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2031 /* Get cipher and hmac name */
2032 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2033 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2035 /* See if the channel exists */
2036 channel = silc_idlist_find_channel_by_name(server->local_list,
2037 channel_name, NULL);
2039 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2040 /* If this is coming from client the Client ID in the command packet must
2041 be same as the client's ID. */
2042 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2043 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2044 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2045 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2046 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2052 /* Channel not found */
2054 /* If we are standalone server we don't have a router, we just create
2055 the channel by ourselves. */
2056 if (server->standalone) {
2057 channel = silc_server_create_new_channel(server, server->id, cipher,
2058 hmac, channel_name, TRUE);
2059 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2064 /* The channel does not exist on our server. If we are normal server
2065 we will send JOIN command to our router which will handle the
2066 joining procedure (either creates the channel if it doesn't exist
2067 or joins the client to it). */
2068 if (server->server_type == SILC_SERVER) {
2070 unsigned short old_ident;
2072 old_ident = silc_command_get_ident(cmd->payload);
2073 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2074 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2076 /* Send JOIN command to our router */
2077 silc_server_packet_send(server, (SilcSocketConnection)
2078 server->router->connection,
2079 SILC_PACKET_COMMAND, cmd->packet->flags,
2080 tmpbuf->data, tmpbuf->len, TRUE);
2082 /* Reprocess this packet after received reply from router */
2083 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2084 silc_command_get_ident(cmd->payload),
2085 silc_server_command_destructor,
2086 silc_server_command_join,
2087 silc_server_command_dup(cmd));
2088 cmd->pending = TRUE;
2092 /* We are router and the channel does not seem exist so we will check
2093 our global list as well for the channel. */
2094 channel = silc_idlist_find_channel_by_name(server->global_list,
2095 channel_name, NULL);
2097 /* Channel really does not exist, create it */
2098 channel = silc_server_create_new_channel(server, server->id, cipher,
2099 hmac, channel_name, TRUE);
2100 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2107 /* Channel not found */
2109 /* If the command came from router and/or we are normal server then
2110 something went wrong with the joining as the channel was not found.
2111 We can't do anything else but ignore this. */
2112 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2113 server->server_type == SILC_SERVER)
2116 /* We are router and the channel does not seem exist so we will check
2117 our global list as well for the channel. */
2118 channel = silc_idlist_find_channel_by_name(server->global_list,
2119 channel_name, NULL);
2121 /* Channel really does not exist, create it */
2122 channel = silc_server_create_new_channel(server, server->id, cipher,
2123 hmac, channel_name, TRUE);
2124 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2130 /* If the channel does not have global users and is also empty it means the
2131 channel was created globally (by our router) and the client will be the
2132 channel founder and operator. */
2133 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2134 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2135 created = TRUE; /* Created globally by our router */
2138 /* Join to the channel */
2139 silc_server_command_join_channel(server, cmd, channel, client_id,
2142 silc_free(client_id);
2145 silc_server_command_free(cmd);
2148 /* Server side of command MOTD. Sends server's current "message of the
2149 day" to the client. */
2151 SILC_SERVER_CMD_FUNC(motd)
2153 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2154 SilcServer server = cmd->server;
2158 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2160 /* XXX show currently only our motd */
2162 if (server->config && server->config->motd &&
2163 server->config->motd->motd_file) {
2166 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2171 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2177 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2182 silc_server_command_free(cmd);
2185 SILC_SERVER_CMD_FUNC(umode)
2189 /* Checks that client has rights to add or remove channel modes. If any
2190 of the checks fails FALSE is returned. */
2192 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2193 SilcChannelClientEntry client,
2196 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2197 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2199 /* Check whether has rights to change anything */
2200 if (!is_op && !is_fo)
2203 /* Check whether has rights to change everything */
2207 /* We know that client is channel operator, check that they are not
2208 changing anything that requires channel founder rights. Rest of the
2209 modes are available automatically for channel operator. */
2211 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2212 if (is_op && !is_fo)
2215 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2216 if (is_op && !is_fo)
2221 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2222 if (is_op && !is_fo)
2225 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2226 if (is_op && !is_fo)
2231 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2232 if (is_op && !is_fo)
2235 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2236 if (is_op && !is_fo)
2244 /* Server side command of CMODE. Changes channel mode */
2246 SILC_SERVER_CMD_FUNC(cmode)
2248 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2249 SilcServer server = cmd->server;
2250 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2251 SilcChannelID *channel_id;
2252 SilcChannelEntry channel;
2253 SilcChannelClientEntry chl;
2254 SilcBuffer packet, cidp;
2255 unsigned char *tmp, *tmp_id, *tmp_mask;
2256 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2258 SILC_LOG_DEBUG(("Start"));
2260 argc = silc_argument_get_arg_num(cmd->args);
2262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2263 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2268 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2272 /* Get Channel ID */
2273 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2276 SILC_STATUS_ERR_NO_CHANNEL_ID);
2279 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2282 SILC_STATUS_ERR_NO_CHANNEL_ID);
2286 /* Get the channel mode mask */
2287 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2289 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2290 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2293 SILC_GET32_MSB(mode_mask, tmp_mask);
2295 /* Get channel entry */
2296 channel = silc_idlist_find_channel_by_id(server->local_list,
2299 channel = silc_idlist_find_channel_by_id(server->global_list,
2302 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2303 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2308 /* Check whether this client is on the channel */
2309 if (!silc_server_client_on_channel(client, channel)) {
2310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2311 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2315 /* Get entry to the channel user list */
2316 silc_list_start(channel->user_list);
2317 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2318 if (chl->client == client)
2321 /* Check that client has rights to change any requested channel modes */
2322 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2323 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2324 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2329 * Check the modes. Modes that requires nothing special operation are
2333 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2334 /* Channel uses private keys to protect traffic. Client(s) has set the
2335 key locally they want to use, server does not know that key. */
2336 /* Nothing interesting to do here now */
2338 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2339 /* The mode is removed and we need to generate and distribute
2340 new channel key. Clients are not using private channel keys
2341 anymore after this. */
2343 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2346 /* Re-generate channel key */
2347 silc_server_create_channel_key(server, channel, 0);
2349 /* Encode channel key payload to be distributed on the channel */
2351 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2352 strlen(channel->channel_key->
2354 channel->channel_key->cipher->name,
2355 channel->key_len / 8, channel->key);
2357 /* If we are normal server then we will send it to our router. If we
2358 are router we will send it to all local servers that has clients on
2360 if (server->server_type == SILC_SERVER) {
2361 if (!server->standalone)
2362 silc_server_packet_send(server,
2363 cmd->server->router->connection,
2364 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2370 /* Send to locally connected clients on the channel */
2371 silc_server_packet_send_local_channel(server, channel,
2372 SILC_PACKET_CHANNEL_KEY, 0,
2373 packet->data, packet->len, FALSE);
2374 silc_buffer_free(packet);
2378 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2379 /* User limit is set on channel */
2380 unsigned int user_limit;
2382 /* Get user limit */
2383 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2385 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2387 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2391 SILC_GET32_MSB(user_limit, tmp);
2392 channel->mode_data.user_limit = user_limit;
2395 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2396 /* User limit mode is unset. Remove user limit */
2397 channel->mode_data.user_limit = 0;
2400 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2401 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2402 /* Passphrase has been set to channel */
2404 /* Get the passphrase */
2405 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2408 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2412 /* Save the passphrase */
2413 channel->mode_data.passphrase = strdup(tmp);
2416 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2417 /* Passphrase mode is unset. remove the passphrase */
2418 if (channel->mode_data.passphrase) {
2419 silc_free(channel->mode_data.passphrase);
2420 channel->mode_data.passphrase = NULL;
2425 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2426 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2427 /* Ban list is specified for channel */
2430 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2433 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2437 /* XXX check that channel founder is not banned */
2439 /* Save the ban list */
2440 channel->mode_data.ban_list = strdup(tmp);
2443 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2444 /* Ban mode is unset. Remove the entire ban list */
2445 if (channel->mode_data.ban_list) {
2446 silc_free(channel->mode_data.ban_list);
2447 channel->mode_data.ban_list = NULL;
2452 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2453 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2454 /* Invite list is specified for channel */
2456 /* Get invite list */
2457 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2459 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2460 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2464 /* Save the invite linst */
2465 channel->mode_data.invite_list = strdup(tmp);
2468 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2469 /* Invite list mode is unset. Remove the entire invite list */
2470 if (channel->mode_data.invite_list) {
2471 silc_free(channel->mode_data.invite_list);
2472 channel->mode_data.invite_list = NULL;
2477 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2478 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2479 /* Cipher to use protect the traffic */
2480 unsigned int key_len;
2483 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2485 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2486 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2490 /* XXX Duplicated code, make own function for this!! */
2492 /* Delete old cipher and allocate the new one */
2493 silc_cipher_free(channel->channel_key);
2494 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
2495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2496 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2499 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
2501 /* Re-generate channel key */
2502 silc_server_create_channel_key(server, channel, key_len);
2504 /* Encode channel key payload to be distributed on the channel */
2506 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2507 strlen(channel->channel_key->
2509 channel->channel_key->cipher->name,
2510 channel->key_len / 8, channel->key);
2512 /* If we are normal server then we will send it to our router. If we
2513 are router we will send it to all local servers that has clients on
2515 if (server->server_type == SILC_SERVER) {
2516 if (!server->standalone)
2517 silc_server_packet_send(server,
2518 cmd->server->router->connection,
2519 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2525 /* Send to locally connected clients on the channel */
2526 silc_server_packet_send_local_channel(server, channel,
2527 SILC_PACKET_CHANNEL_KEY, 0,
2528 packet->data, packet->len, FALSE);
2529 silc_buffer_free(packet);
2532 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2533 /* Cipher mode is unset. Remove the cipher and revert back to
2536 if (channel->mode_data.cipher) {
2537 silc_free(channel->mode_data.cipher);
2538 channel->mode_data.cipher = NULL;
2539 channel->mode_data.key_len = 0;
2542 /* Generate new cipher and key for the channel */
2544 /* XXX Duplicated code, make own function for this!! */
2546 /* Delete old cipher and allocate default one */
2547 silc_cipher_free(channel->channel_key);
2548 if (!channel->cipher)
2549 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
2551 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
2552 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2553 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2558 /* Re-generate channel key */
2559 silc_server_create_channel_key(server, channel, 0);
2561 /* Encode channel key payload to be distributed on the channel */
2563 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2564 strlen(channel->channel_key->
2566 channel->channel_key->cipher->name,
2567 channel->key_len / 8, channel->key);
2569 /* If we are normal server then we will send it to our router. If we
2570 are router we will send it to all local servers that has clients on
2572 if (server->server_type == SILC_SERVER) {
2573 if (!server->standalone)
2574 silc_server_packet_send(server,
2575 cmd->server->router->connection,
2576 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2582 /* Send to locally connected clients on the channel */
2583 silc_server_packet_send_local_channel(server, channel,
2584 SILC_PACKET_CHANNEL_KEY, 0,
2585 packet->data, packet->len, FALSE);
2586 silc_buffer_free(packet);
2590 /* Finally, set the mode */
2591 channel->mode = mode_mask;
2593 /* Send CMODE_CHANGE notify */
2594 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2595 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2596 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2597 cidp->data, cidp->len,
2600 /* Set CMODE notify type to network */
2601 if (!server->standalone)
2602 silc_server_send_notify_cmode(server, server->router->connection,
2603 server->server_type == SILC_ROUTER ?
2604 TRUE : FALSE, channel,
2605 mode_mask, client->id, SILC_ID_CLIENT_LEN);
2607 /* Send command reply to sender */
2608 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2609 SILC_STATUS_OK, 0, 1,
2611 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2612 packet->data, packet->len, FALSE);
2614 silc_buffer_free(packet);
2615 silc_free(channel_id);
2619 silc_server_command_free(cmd);
2622 /* Server side of CUMODE command. Changes client's mode on a channel. */
2624 SILC_SERVER_CMD_FUNC(cumode)
2626 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2627 SilcServer server = cmd->server;
2628 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2629 SilcChannelID *channel_id;
2630 SilcClientID *client_id;
2631 SilcChannelEntry channel;
2632 SilcClientEntry target_client;
2633 SilcChannelClientEntry chl;
2634 SilcBuffer packet, idp;
2635 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2636 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
2639 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2641 /* Get Channel ID */
2642 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2644 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2645 SILC_STATUS_ERR_NO_CHANNEL_ID);
2648 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
2650 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2651 SILC_STATUS_ERR_NO_CHANNEL_ID);
2655 /* Get channel entry */
2656 channel = silc_idlist_find_channel_by_id(server->local_list,
2659 channel = silc_idlist_find_channel_by_id(server->global_list,
2662 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2663 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2668 /* Check whether sender is on the channel */
2669 if (!silc_server_client_on_channel(client, channel)) {
2670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2671 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2675 /* Check that client has rights to change other's rights */
2676 silc_list_start(channel->user_list);
2677 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2678 if (chl->client == client) {
2679 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2680 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2682 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2686 sender_mask = chl->mode;
2691 /* Get the target client's channel mode mask */
2692 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2695 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2698 SILC_GET32_MSB(target_mask, tmp_mask);
2700 /* Get target Client ID */
2701 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2704 SILC_STATUS_ERR_NO_CLIENT_ID);
2707 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2709 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2710 SILC_STATUS_ERR_NO_CLIENT_ID);
2714 /* Get target client's entry */
2715 target_client = silc_idlist_find_client_by_id(server->local_list,
2717 if (!target_client) {
2718 target_client = silc_idlist_find_client_by_id(server->global_list,
2722 /* Check whether target client is on the channel */
2723 if (!silc_server_client_on_channel(target_client, channel)) {
2724 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2725 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2729 /* Get entry to the channel user list */
2730 silc_list_start(channel->user_list);
2731 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2732 if (chl->client == target_client)
2739 /* If the target client is founder, no one else can change their mode
2741 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2742 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2743 SILC_STATUS_ERR_NOT_YOU);
2747 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2748 /* Cannot promote anyone to channel founder */
2749 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2750 SILC_STATUS_ERR_NOT_YOU);
2753 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2754 if (target_client == client) {
2755 /* Remove channel founder rights from itself */
2756 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2759 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2760 SILC_STATUS_ERR_NOT_YOU);
2766 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2767 /* Promote to operator */
2768 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2769 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2773 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2774 /* Demote to normal user */
2775 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2780 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2782 /* Send notify to channel, notify only if mode was actually changed. */
2784 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2785 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2786 idp->data, idp->len,
2790 /* Set CUMODE notify type to network */
2791 if (!server->standalone)
2792 silc_server_send_notify_cumode(server, server->router->connection,
2793 server->server_type == SILC_ROUTER ?
2794 TRUE : FALSE, channel,
2795 target_mask, client->id,
2798 SILC_ID_CLIENT_LEN);
2801 /* Send command reply to sender */
2802 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2803 SILC_STATUS_OK, 0, 2,
2805 3, tmp_id, tmp_len);
2806 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2807 packet->data, packet->len, FALSE);
2809 silc_buffer_free(packet);
2810 silc_free(channel_id);
2811 silc_free(client_id);
2812 silc_buffer_free(idp);
2815 silc_server_command_free(cmd);
2818 /* Server side of KICK command. Kicks client out of channel. */
2820 SILC_SERVER_CMD_FUNC(kick)
2822 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2823 SilcServer server = cmd->server;
2824 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2825 SilcClientEntry target_client;
2826 SilcChannelID *channel_id;
2827 SilcClientID *client_id;
2828 SilcChannelEntry channel;
2829 SilcChannelClientEntry chl;
2831 unsigned int tmp_len;
2832 unsigned char *tmp, *comment;
2834 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
2836 /* Get Channel ID */
2837 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2839 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2840 SILC_STATUS_ERR_NO_CHANNEL_ID);
2843 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2845 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2846 SILC_STATUS_ERR_NO_CHANNEL_ID);
2850 /* Get channel entry */
2851 channel = silc_idlist_find_channel_by_id(server->local_list,
2854 channel = silc_idlist_find_channel_by_id(server->local_list,
2857 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2858 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2863 /* Check whether sender is on the channel */
2864 if (!silc_server_client_on_channel(client, channel)) {
2865 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2866 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2870 /* Check that the kicker is channel operator or channel founder */
2871 silc_list_start(channel->user_list);
2872 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2873 if (chl->client == client) {
2874 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2875 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2876 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2883 /* Get target Client ID */
2884 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2886 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2887 SILC_STATUS_ERR_NO_CLIENT_ID);
2890 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2892 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2893 SILC_STATUS_ERR_NO_CLIENT_ID);
2897 /* Get target client's entry */
2898 target_client = silc_idlist_find_client_by_id(server->local_list,
2900 if (!target_client) {
2901 target_client = silc_idlist_find_client_by_id(server->global_list,
2905 /* Check that the target client is not channel founder. Channel founder
2906 cannot be kicked from the channel. */
2907 silc_list_start(channel->user_list);
2908 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2909 if (chl->client == target_client) {
2910 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2912 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
2919 /* Check whether target client is on the channel */
2920 if (!silc_server_client_on_channel(target_client, channel)) {
2921 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2922 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2928 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2932 /* Send command reply to sender */
2933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2936 /* Send KICKED notify to local clients on the channel */
2937 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
2938 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2939 SILC_NOTIFY_TYPE_KICKED,
2941 idp->data, idp->len,
2942 comment, comment ? strlen(comment) : 0);
2943 silc_buffer_free(idp);
2945 /* Remove the client from the channel. If the channel does not exist
2946 after removing the client then the client kicked itself of the channel
2947 and we don't have to send anything after that. */
2948 if (!silc_server_remove_from_one_channel(server, NULL, channel,
2949 target_client, FALSE))
2952 /* Send KICKED notify to primary route */
2953 if (!server->standalone)
2954 silc_server_send_notify_kicked(server, server->router->connection,
2955 server->server_type == SILC_ROUTER ?
2956 TRUE : FALSE, channel,
2957 target_client->id, SILC_ID_CLIENT_LEN,
2960 /* Re-generate channel key */
2961 silc_server_create_channel_key(server, channel, 0);
2963 /* Send the channel key to the channel. The key of course is not sent
2964 to the client who joined the channel. */
2965 silc_server_send_channel_key(server, target_client->connection, channel,
2966 server->server_type == SILC_ROUTER ?
2967 FALSE : !server->standalone);
2970 silc_server_command_free(cmd);
2973 SILC_SERVER_CMD_FUNC(oper)
2977 SILC_SERVER_CMD_FUNC(silcoper)
2981 /* Server side command of CONNECT. Connects us to the specified remote
2982 server or router. */
2984 SILC_SERVER_CMD_FUNC(connect)
2986 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2987 SilcServer server = cmd->server;
2988 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2990 unsigned int tmp_len;
2991 unsigned int port = SILC_PORT;
2993 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
2995 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2998 /* Check whether client has the permissions. */
2999 if (client->mode == SILC_UMODE_NONE) {
3000 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3001 SILC_STATUS_ERR_NO_SERVER_PRIV);
3005 if (server->server_type == SILC_ROUTER &&
3006 client->mode & SILC_UMODE_SERVER_OPERATOR) {
3007 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3008 SILC_STATUS_ERR_NO_ROUTER_PRIV);
3012 /* Get the remote server */
3013 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3015 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3016 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3021 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3023 SILC_GET32_MSB(port, tmp);
3025 /* Create the connection. It is done with timeout and is async. */
3026 silc_server_create_connection(server, tmp, port);
3028 /* Send reply to the sender */
3029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3033 silc_server_command_free(cmd);
3036 SILC_SERVER_CMD_FUNC(restart)
3040 /* Server side command of CLOSE. Closes connection to a specified server. */
3042 SILC_SERVER_CMD_FUNC(close)
3044 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3045 SilcServer server = cmd->server;
3046 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3047 SilcServerEntry server_entry;
3049 unsigned int tmp_len;
3050 unsigned char *name;
3051 unsigned int port = SILC_PORT;
3053 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3055 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3058 /* Check whether client has the permissions. */
3059 if (client->mode == SILC_UMODE_NONE) {
3060 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3061 SILC_STATUS_ERR_NO_SERVER_PRIV);
3065 /* Get the remote server */
3066 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3068 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3069 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3074 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3076 SILC_GET32_MSB(port, tmp);
3078 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3080 if (!server_entry) {
3081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3082 SILC_STATUS_ERR_NO_SERVER_ID);
3086 /* Close the connection to the server */
3087 silc_server_free_sock_user_data(server, server_entry->connection);
3088 silc_server_disconnect_remote(server, server_entry->connection,
3089 "Server closed connection: "
3090 "Closed by operator");
3092 /* Send reply to the sender */
3093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3097 silc_server_command_free(cmd);
3100 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3101 active connections. */
3103 SILC_SERVER_CMD_FUNC(shutdown)
3105 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3106 SilcServer server = cmd->server;
3107 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3109 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3111 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3114 /* Check whether client has the permission. */
3115 if (client->mode == SILC_UMODE_NONE) {
3116 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3117 SILC_STATUS_ERR_NO_SERVER_PRIV);
3121 /* Then, gracefully, or not, bring the server down. */
3122 silc_server_stop(server);
3124 /* Send reply to the sender */
3125 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3129 silc_server_command_free(cmd);
3132 /* Server side command of LEAVE. Removes client from a channel. */
3134 SILC_SERVER_CMD_FUNC(leave)
3136 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3137 SilcServer server = cmd->server;
3138 SilcSocketConnection sock = cmd->sock;
3139 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3141 SilcChannelEntry channel;
3143 unsigned int i, len;
3146 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3148 /* Get Channel ID */
3149 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3151 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3152 SILC_STATUS_ERR_NO_CHANNEL_ID);
3155 id = silc_id_payload_parse_id(tmp, len);
3157 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3158 SILC_STATUS_ERR_NO_CHANNEL_ID);
3162 /* Get channel entry */
3163 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3165 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3168 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3173 /* Check whether this client is on the channel */
3174 if (!silc_server_client_on_channel(id_entry, channel)) {
3175 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3176 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3180 /* Notify routers that they should remove this client from their list
3181 of clients on the channel. Send LEAVE notify type. */
3182 if (!server->standalone)
3183 silc_server_send_notify_leave(server, server->router->connection,
3184 server->server_type == SILC_ROUTER ?
3185 TRUE : FALSE, channel, id_entry->id,
3186 SILC_ID_CLIENT_LEN);
3188 /* Remove client from channel */
3189 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3194 /* If the channel does not exist anymore we won't send anything */
3198 /* Re-generate channel key */
3199 silc_server_create_channel_key(server, channel, 0);
3201 /* Encode channel key payload to be distributed on the channel */
3203 silc_channel_key_payload_encode(len, tmp,
3204 strlen(channel->channel_key->cipher->name),
3205 channel->channel_key->cipher->name,
3206 channel->key_len / 8, channel->key);
3208 /* If we are normal server then we will send it to our router. If we
3209 are router we will send it to all local servers that has clients on
3211 if (server->server_type == SILC_SERVER) {
3212 if (!server->standalone)
3213 silc_server_packet_send(server,
3214 cmd->server->router->connection,
3215 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3216 packet->len, FALSE);
3221 /* Send to locally connected clients on the channel */
3222 silc_server_packet_send_local_channel(server, channel,
3223 SILC_PACKET_CHANNEL_KEY, 0,
3224 packet->data, packet->len, FALSE);
3226 silc_buffer_free(packet);
3230 silc_server_command_free(cmd);
3233 /* Server side of command USERS. Resolves clients and their USERS currently
3234 joined on the requested channel. The list of Client ID's and their modes
3235 on the channel is sent back. */
3237 SILC_SERVER_CMD_FUNC(users)
3239 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3240 SilcServer server = cmd->server;
3241 SilcChannelEntry channel;
3242 SilcChannelClientEntry chl;
3245 unsigned char *channel_id;
3246 unsigned int channel_id_len;
3247 SilcBuffer client_id_list;
3248 SilcBuffer client_mode_list;
3250 unsigned char lc[4];
3251 unsigned int list_count = 0;
3252 unsigned short ident = silc_command_get_ident(cmd->payload);
3254 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3256 /* Get Channel ID */
3257 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3259 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3260 SILC_STATUS_ERR_NO_CHANNEL_ID);
3263 id = silc_id_payload_parse_id(channel_id, channel_id_len);
3265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3266 SILC_STATUS_ERR_NO_CHANNEL_ID);
3270 /* If we are server and we don't know about this channel we will send
3271 the command to our router. If we know about the channel then we also
3272 have the list of users already. */
3273 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3275 if (server->server_type == SILC_SERVER && !server->standalone &&
3279 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3280 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3282 /* Send USERS command */
3283 silc_server_packet_send(server, server->router->connection,
3284 SILC_PACKET_COMMAND, cmd->packet->flags,
3285 tmpbuf->data, tmpbuf->len, TRUE);
3287 /* Reprocess this packet after received reply */
3288 silc_server_command_pending(server, SILC_COMMAND_USERS,
3289 silc_command_get_ident(cmd->payload),
3290 silc_server_command_destructor,
3291 silc_server_command_users,
3292 silc_server_command_dup(cmd));
3293 cmd->pending = TRUE;
3294 silc_command_set_ident(cmd->payload, ident);
3296 silc_buffer_free(tmpbuf);
3301 /* We are router and we will check the global list as well. */
3302 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3304 /* Channel really does not exist */
3305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3306 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3311 /* Assemble the lists now */
3313 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
3314 silc_list_count(channel->user_list));
3315 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
3317 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
3318 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
3320 silc_list_start(channel->user_list);
3321 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3323 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
3324 silc_buffer_put(client_id_list, idp->data, idp->len);
3325 silc_buffer_pull(client_id_list, idp->len);
3326 silc_buffer_free(idp);
3328 /* Client's mode on channel */
3329 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
3330 silc_buffer_pull(client_mode_list, 4);
3334 silc_buffer_push(client_id_list,
3335 client_id_list->data - client_id_list->head);
3336 silc_buffer_push(client_mode_list,
3337 client_mode_list->data - client_mode_list->head);
3340 SILC_PUT32_MSB(list_count, lc);
3343 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3344 SILC_STATUS_OK, 0, 4,
3345 2, channel_id, channel_id_len,
3347 4, client_id_list->data,
3348 client_id_list->len,
3349 5, client_mode_list->data,
3350 client_mode_list->len);
3351 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3352 packet->data, packet->len, FALSE);
3354 silc_buffer_free(packet);
3355 silc_buffer_free(client_id_list);
3356 silc_buffer_free(client_mode_list);
3360 silc_server_command_free(cmd);