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,
634 clients = silc_idlist_get_clients_by_hash(server->local_list,
635 nick, server->md5hash,
639 /* Check global list as well */
641 if (client_id_count) {
642 /* Check all Client ID's received in the command packet */
643 for (i = 0; i < client_id_count; i++) {
644 entry = silc_idlist_find_client_by_id(server->global_list,
647 clients = silc_realloc(clients, sizeof(*clients) *
648 (clients_count + 1));
649 clients[clients_count++] = entry;
653 clients = silc_idlist_get_clients_by_nickname(server->global_list,
657 clients = silc_idlist_get_clients_by_hash(server->global_list,
658 nick, server->md5hash,
664 /* Such client(s) really does not exist in the SILC network. */
665 if (!client_id_count) {
666 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
667 SILC_STATUS_ERR_NO_SUCH_NICK,
668 3, nick, strlen(nick));
670 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
671 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
672 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
673 2, idp->data, idp->len);
674 silc_buffer_free(idp);
679 /* Router always finds the client entry if it exists in the SILC network.
680 However, it might be incomplete entry and does not include all the
681 mandatory fields that WHOIS command reply requires. Check for these and
682 make query from the server who owns the client if some fields are
684 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
689 /* Send the command reply to the client */
690 silc_server_command_whois_send_reply(cmd, clients, clients_count);
693 if (client_id_count) {
694 for (i = 0; i < client_id_count; i++)
695 silc_free(client_id[i]);
696 silc_free(client_id);
703 silc_free(server_name);
709 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
711 SilcServer server = cmd->server;
712 char *nick = NULL, *server_name = NULL;
713 int count = 0, clients_count = 0;
714 SilcClientEntry *clients = NULL, entry;
715 SilcClientID **client_id = NULL;
716 unsigned int client_id_count = 0;
719 /* Parse the whois request */
720 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
721 &nick, &server_name, &count,
725 /* Process the command request. Let's search for the requested client and
726 send reply to the requesting server. */
728 if (client_id_count) {
729 /* Check all Client ID's received in the command packet */
730 for (i = 0; i < client_id_count; i++) {
731 entry = silc_idlist_find_client_by_id(server->local_list,
734 clients = silc_realloc(clients, sizeof(*clients) *
735 (clients_count + 1));
736 clients[clients_count++] = entry;
740 clients = silc_idlist_get_clients_by_nickname(server->local_list,
744 clients = silc_idlist_get_clients_by_hash(server->local_list,
745 nick, server->md5hash,
749 /* If we are router we will check our global list as well. */
750 if (!clients && server->server_type == SILC_ROUTER) {
751 if (client_id_count) {
752 /* Check all Client ID's received in the command packet */
753 for (i = 0; i < client_id_count; i++) {
754 entry = silc_idlist_find_client_by_id(server->global_list,
757 clients = silc_realloc(clients, sizeof(*clients) *
758 (clients_count + 1));
759 clients[clients_count++] = entry;
763 clients = silc_idlist_get_clients_by_nickname(server->global_list,
767 clients = silc_idlist_get_clients_by_hash(server->global_list,
768 nick, server->md5hash,
774 /* Such a client really does not exist in the SILC network. */
775 if (!client_id_count) {
776 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
777 SILC_STATUS_ERR_NO_SUCH_NICK,
778 3, nick, strlen(nick));
780 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
781 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
782 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
783 2, idp->data, idp->len);
784 silc_buffer_free(idp);
789 /* Router always finds the client entry if it exists in the SILC network.
790 However, it might be incomplete entry and does not include all the
791 mandatory fields that WHOIS command reply requires. Check for these and
792 make query from the server who owns the client if some fields are
794 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
799 /* Send the command reply to the client */
800 silc_server_command_whois_send_reply(cmd, clients, clients_count);
803 if (client_id_count) {
804 for (i = 0; i < client_id_count; i++)
805 silc_free(client_id[i]);
806 silc_free(client_id);
813 silc_free(server_name);
818 /* Server side of command WHOIS. Processes user's query and sends found
819 results as command replies back to the client. */
821 SILC_SERVER_CMD_FUNC(whois)
823 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
826 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
828 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
829 ret = silc_server_command_whois_from_client(cmd);
830 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
831 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
832 ret = silc_server_command_whois_from_server(cmd);
835 silc_server_command_free(cmd);
838 SILC_SERVER_CMD_FUNC(whowas)
842 /******************************************************************************
846 ******************************************************************************/
848 /* Checks that all mandatory fields are present. If not then send WHOIS
849 request to the server who owns the client. We use WHOIS because we want
850 to get as much information as possible at once. */
853 silc_server_command_identify_check(SilcServerCommandContext cmd,
854 SilcClientEntry *clients,
855 unsigned int clients_count)
857 SilcServer server = cmd->server;
859 SilcClientEntry entry;
861 for (i = 0; i < clients_count; i++) {
864 if (!entry->nickname) {
866 unsigned short old_ident;
871 old_ident = silc_command_get_ident(cmd->payload);
872 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
873 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
874 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
876 /* Send WHOIS request. We send WHOIS since we're doing the requesting
877 now anyway so make it a good one. */
878 silc_server_packet_send(server, entry->router->connection,
879 SILC_PACKET_COMMAND, cmd->packet->flags,
880 tmpbuf->data, tmpbuf->len, TRUE);
882 /* Reprocess this packet after received reply */
883 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
884 silc_command_get_ident(cmd->payload),
885 silc_server_command_destructor,
886 silc_server_command_identify,
887 silc_server_command_dup(cmd));
891 /* Put old data back to the Command Payload we just changed */
892 silc_command_set_ident(cmd->payload, old_ident);
893 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
895 silc_buffer_free(tmpbuf);
904 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
905 SilcClientEntry *clients,
906 unsigned int clients_count)
908 SilcServer server = cmd->server;
910 int i, count = 0, len;
911 SilcBuffer packet, idp;
912 SilcClientEntry entry;
913 SilcCommandStatus status;
914 unsigned short ident = silc_command_get_ident(cmd->payload);
916 status = SILC_STATUS_OK;
917 if (clients_count > 1)
918 status = SILC_STATUS_LIST_START;
920 for (i = 0; i < clients_count; i++) {
923 if (count && i - 1 == count)
926 if (clients_count > 2)
927 status = SILC_STATUS_LIST_ITEM;
929 if (clients_count > 1 && i == clients_count - 1)
930 status = SILC_STATUS_LIST_END;
932 /* Send IDENTIFY reply */
933 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
934 tmp = silc_argument_get_first_arg(cmd->args, NULL);
938 char nh[256], uh[256];
939 SilcSocketConnection hsock;
941 memset(uh, 0, sizeof(uh));
942 memset(nh, 0, sizeof(nh));
944 strncat(nh, entry->nickname, strlen(entry->nickname));
945 if (!strchr(entry->nickname, '@')) {
947 len = entry->router ? strlen(entry->router->server_name) :
948 strlen(server->server_name);
949 strncat(nh, entry->router ? entry->router->server_name :
950 server->server_name, len);
953 if (!entry->username) {
954 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
955 SILC_STATUS_OK, ident, 2,
956 2, idp->data, idp->len,
959 strncat(uh, entry->username, strlen(entry->username));
960 if (!strchr(entry->username, '@')) {
962 hsock = (SilcSocketConnection)entry->connection;
963 len = strlen(hsock->hostname);
964 strncat(uh, hsock->hostname, len);
967 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
968 SILC_STATUS_OK, ident, 3,
969 2, idp->data, idp->len,
974 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
975 0, packet->data, packet->len, FALSE);
977 silc_buffer_free(packet);
978 silc_buffer_free(idp);
984 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
986 SilcServer server = cmd->server;
987 char *nick = NULL, *server_name = NULL;
988 int count = 0, clients_count = 0;
989 SilcClientEntry *clients = NULL, entry;
990 SilcClientID **client_id = NULL;
991 unsigned int client_id_count = 0;
994 /* Protocol dictates that we must always send the received IDENTIFY request
995 to our router if we are normal server, so let's do it now unless we
996 are standalone. We will not send any replies to the client until we
997 have received reply from the router. */
998 if (server->server_type == SILC_SERVER &&
999 !cmd->pending && !server->standalone) {
1001 unsigned short old_ident;
1003 old_ident = silc_command_get_ident(cmd->payload);
1004 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1005 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1007 /* Send IDENTIFY command to our router */
1008 silc_server_packet_send(server, (SilcSocketConnection)
1009 server->router->connection,
1010 SILC_PACKET_COMMAND, cmd->packet->flags,
1011 tmpbuf->data, tmpbuf->len, TRUE);
1013 /* Reprocess this packet after received reply from router */
1014 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1015 silc_command_get_ident(cmd->payload),
1016 silc_server_command_destructor,
1017 silc_server_command_identify,
1018 silc_server_command_dup(cmd));
1019 cmd->pending = TRUE;
1021 silc_command_set_ident(cmd->payload, old_ident);
1023 silc_buffer_free(tmpbuf);
1028 /* We are ready to process the command request. Let's search for the
1029 requested client and send reply to the requesting client. */
1031 /* Parse the IDENTIFY request */
1032 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1033 &nick, &server_name, &count,
1034 SILC_COMMAND_IDENTIFY))
1037 /* Get all clients matching that ID or nickname from local list */
1038 if (client_id_count) {
1039 /* Check all Client ID's received in the command packet */
1040 for (i = 0; i < client_id_count; i++) {
1041 entry = silc_idlist_find_client_by_id(server->local_list,
1042 client_id[i], NULL);
1044 clients = silc_realloc(clients, sizeof(*clients) *
1045 (clients_count + 1));
1046 clients[clients_count++] = entry;
1050 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1054 clients = silc_idlist_get_clients_by_hash(server->local_list,
1055 nick, server->md5hash,
1059 /* Check global list as well */
1061 if (client_id_count) {
1062 /* Check all Client ID's received in the command packet */
1063 for (i = 0; i < client_id_count; i++) {
1064 entry = silc_idlist_find_client_by_id(server->global_list,
1065 client_id[i], NULL);
1067 clients = silc_realloc(clients, sizeof(*clients) *
1068 (clients_count + 1));
1069 clients[clients_count++] = entry;
1073 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1077 clients = silc_idlist_get_clients_by_hash(server->global_list,
1078 nick, server->md5hash,
1084 /* Such a client really does not exist in the SILC network. */
1085 if (!client_id_count) {
1086 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1087 SILC_STATUS_ERR_NO_SUCH_NICK,
1088 3, nick, strlen(nick));
1090 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1091 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1092 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1093 2, idp->data, idp->len);
1094 silc_buffer_free(idp);
1099 /* Check that all mandatory fields are present and request those data
1100 from the server who owns the client if necessary. */
1101 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1106 /* Send the command reply to the client */
1107 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1110 if (client_id_count) {
1111 for (i = 0; i < client_id_count; i++)
1112 silc_free(client_id[i]);
1113 silc_free(client_id);
1120 silc_free(server_name);
1126 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1128 SilcServer server = cmd->server;
1129 char *nick = NULL, *server_name = NULL;
1130 int count = 0, clients_count = 0;
1131 SilcClientEntry *clients = NULL, entry;
1132 SilcClientID **client_id = NULL;
1133 unsigned int client_id_count = 0;
1136 /* Parse the IDENTIFY request */
1137 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1138 &nick, &server_name, &count,
1139 SILC_COMMAND_IDENTIFY))
1142 /* Process the command request. Let's search for the requested client and
1143 send reply to the requesting server. */
1145 if (client_id_count) {
1146 /* Check all Client ID's received in the command packet */
1147 for (i = 0; i < client_id_count; i++) {
1148 entry = silc_idlist_find_client_by_id(server->local_list,
1149 client_id[i], NULL);
1151 clients = silc_realloc(clients, sizeof(*clients) *
1152 (clients_count + 1));
1153 clients[clients_count++] = entry;
1157 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1161 clients = silc_idlist_get_clients_by_hash(server->local_list,
1162 nick, server->md5hash,
1166 /* If we are router we will check our global list as well. */
1167 if (!clients && server->server_type == SILC_ROUTER) {
1168 if (client_id_count) {
1169 /* Check all Client ID's received in the command packet */
1170 for (i = 0; i < client_id_count; i++) {
1171 entry = silc_idlist_find_client_by_id(server->global_list,
1172 client_id[i], NULL);
1174 clients = silc_realloc(clients, sizeof(*clients) *
1175 (clients_count + 1));
1176 clients[clients_count++] = entry;
1180 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1184 clients = silc_idlist_get_clients_by_hash(server->global_list,
1185 nick, server->md5hash,
1191 /* Such a client really does not exist in the SILC network. */
1192 if (!client_id_count) {
1193 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1194 SILC_STATUS_ERR_NO_SUCH_NICK,
1195 3, nick, strlen(nick));
1197 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1198 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1199 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1200 2, idp->data, idp->len);
1201 silc_buffer_free(idp);
1206 /* Check that all mandatory fields are present and request those data
1207 from the server who owns the client if necessary. */
1208 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1213 /* Send the command reply */
1214 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1217 if (client_id_count) {
1218 for (i = 0; i < client_id_count; i++)
1219 silc_free(client_id[i]);
1220 silc_free(client_id);
1227 silc_free(server_name);
1232 SILC_SERVER_CMD_FUNC(identify)
1234 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1237 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1239 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1240 ret = silc_server_command_identify_from_client(cmd);
1241 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1242 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1243 ret = silc_server_command_identify_from_server(cmd);
1246 silc_server_command_free(cmd);
1249 /* Checks string for bad characters and returns TRUE if they are found. */
1251 static int silc_server_command_bad_chars(char *nick)
1253 if (strchr(nick, '\\')) return TRUE;
1254 if (strchr(nick, '\"')) return TRUE;
1255 if (strchr(nick, '´')) return TRUE;
1256 if (strchr(nick, '`')) return TRUE;
1257 if (strchr(nick, '\'')) return TRUE;
1258 if (strchr(nick, '*')) return TRUE;
1259 if (strchr(nick, '/')) return TRUE;
1260 if (strchr(nick, '@')) return TRUE;
1265 /* Server side of command NICK. Sets nickname for user. Setting
1266 nickname causes generation of a new client ID for the client. The
1267 new client ID is sent to the client after changing the nickname. */
1269 SILC_SERVER_CMD_FUNC(nick)
1271 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1272 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1273 SilcServer server = cmd->server;
1274 SilcBuffer packet, nidp, oidp;
1275 SilcClientID *new_id;
1278 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1280 /* Check nickname */
1281 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1282 if (silc_server_command_bad_chars(nick) == TRUE) {
1283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1284 SILC_STATUS_ERR_BAD_NICKNAME);
1288 /* Create new Client ID */
1289 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1290 cmd->server->md5hash, nick,
1293 /* Send notify about nickname change to our router. We send the new
1294 ID and ask to replace it with the old one. If we are router the
1295 packet is broadcasted. Send NICK_CHANGE notify. */
1296 if (!server->standalone)
1297 silc_server_send_notify_nick_change(server, server->router->connection,
1298 server->server_type == SILC_SERVER ?
1299 FALSE : TRUE, client->id,
1300 new_id, SILC_ID_CLIENT_LEN);
1302 /* Remove old cache entry */
1303 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1306 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1310 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1311 silc_free(client->id);
1314 /* Save the nickname as this client is our local client */
1315 if (client->nickname)
1316 silc_free(client->nickname);
1318 client->nickname = strdup(nick);
1319 client->id = new_id;
1321 /* Update client cache */
1322 silc_idcache_add(server->local_list->clients, client->nickname,
1323 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1325 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1327 /* Send NICK_CHANGE notify to the client's channels */
1328 silc_server_send_notify_on_channels(server, client,
1329 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1330 oidp->data, oidp->len,
1331 nidp->data, nidp->len);
1333 /* Send the new Client ID as reply command back to client */
1334 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1335 SILC_STATUS_OK, 0, 1,
1336 2, nidp->data, nidp->len);
1337 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1338 0, packet->data, packet->len, FALSE);
1340 silc_buffer_free(packet);
1341 silc_buffer_free(nidp);
1342 silc_buffer_free(oidp);
1345 silc_server_command_free(cmd);
1348 SILC_SERVER_CMD_FUNC(list)
1352 /* Server side of TOPIC command. Sets topic for channel and/or returns
1353 current topic to client. */
1355 SILC_SERVER_CMD_FUNC(topic)
1357 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1358 SilcServer server = cmd->server;
1359 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1360 SilcChannelID *channel_id;
1361 SilcChannelEntry channel;
1362 SilcChannelClientEntry chl;
1363 SilcBuffer packet, idp;
1365 unsigned int argc, tmp_len;
1367 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1369 argc = silc_argument_get_arg_num(cmd->args);
1371 /* Get Channel ID */
1372 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1375 SILC_STATUS_ERR_NO_CHANNEL_ID);
1378 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1380 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1381 SILC_STATUS_ERR_NO_CHANNEL_ID);
1385 /* Check whether the channel exists */
1386 channel = silc_idlist_find_channel_by_id(server->local_list,
1389 channel = silc_idlist_find_channel_by_id(server->global_list,
1392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1393 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1400 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1403 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1407 if (strlen(tmp) > 256) {
1408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1409 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1413 /* See whether has rights to change topic */
1414 silc_list_start(channel->user_list);
1415 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1416 if (chl->client == client)
1419 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1420 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1422 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1427 /* Set the topic for channel */
1429 silc_free(channel->topic);
1430 channel->topic = strdup(tmp);
1432 /* Send TOPIC_SET notify type to the network */
1433 if (!server->standalone)
1434 silc_server_send_notify_topic_set(server, server->router->connection,
1435 server->server_type == SILC_ROUTER ?
1436 TRUE : FALSE, channel, client->id,
1437 SILC_ID_CLIENT_LEN, channel->topic);
1439 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1441 /* Send notify about topic change to all clients on the channel */
1442 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1443 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1444 idp->data, idp->len,
1445 channel->topic, strlen(channel->topic));
1446 silc_buffer_free(idp);
1449 /* Send the topic to client as reply packet */
1450 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1452 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1453 SILC_STATUS_OK, 0, 2,
1454 2, idp->data, idp->len,
1456 strlen(channel->topic));
1458 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1459 SILC_STATUS_OK, 0, 1,
1460 2, idp->data, idp->len);
1461 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1462 0, packet->data, packet->len, FALSE);
1464 silc_buffer_free(packet);
1465 silc_buffer_free(idp);
1466 silc_free(channel_id);
1469 silc_server_command_free(cmd);
1472 /* Server side of INVITE command. Invites some client to join some channel. */
1474 SILC_SERVER_CMD_FUNC(invite)
1476 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1477 SilcServer server = cmd->server;
1478 SilcSocketConnection sock = cmd->sock, dest_sock;
1479 SilcClientEntry sender, dest;
1480 SilcClientID *dest_id;
1481 SilcChannelEntry channel;
1482 SilcChannelID *channel_id;
1487 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1489 /* Get destination ID */
1490 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1492 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1493 SILC_STATUS_ERR_NO_CLIENT_ID);
1496 dest_id = silc_id_payload_parse_id(tmp, len);
1498 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1499 SILC_STATUS_ERR_NO_CLIENT_ID);
1503 /* Get Channel ID */
1504 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1506 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1507 SILC_STATUS_ERR_NO_CHANNEL_ID);
1510 channel_id = silc_id_payload_parse_id(tmp, len);
1512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1513 SILC_STATUS_ERR_NO_CHANNEL_ID);
1517 /* Check whether the channel exists */
1518 channel = silc_idlist_find_channel_by_id(server->local_list,
1521 channel = silc_idlist_find_channel_by_id(server->global_list,
1524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1525 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1530 /* Check whether the sender of this command is on the channel. */
1531 sender = (SilcClientEntry)sock->user_data;
1532 if (!silc_server_client_on_channel(sender, channel)) {
1533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1534 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1538 /* Check whether the channel is invite-only channel. If yes then the
1539 sender of this command must be at least channel operator. */
1540 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1541 SilcChannelClientEntry chl;
1543 silc_list_start(channel->user_list);
1544 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1545 if (chl->client == sender) {
1546 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1547 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1548 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1555 /* Find the connection data for the destination. If it is local we will
1556 send it directly otherwise we will send it to router for routing. */
1557 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1559 dest_sock = (SilcSocketConnection)dest->connection;
1561 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1563 /* Check whether the requested client is already on the channel. */
1564 /* XXX if we are normal server we don't know about global clients on
1565 the channel thus we must request it (USERS command), check from
1566 local cache as well. */
1567 if (silc_server_client_on_channel(dest, channel)) {
1568 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1569 SILC_STATUS_ERR_USER_ON_CHANNEL);
1573 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1575 /* Send notify to the client that is invited to the channel */
1576 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1578 SILC_NOTIFY_TYPE_INVITE, 2,
1579 sidp->data, sidp->len, tmp, len);
1581 /* Send command reply */
1582 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1585 silc_buffer_free(sidp);
1588 silc_server_command_free(cmd);
1593 SilcSocketConnection sock;
1597 /* Quits connection to client. This gets called if client won't
1598 close the connection even when it has issued QUIT command. */
1600 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1602 QuitInternal q = (QuitInternal)context;
1604 /* Free all client specific data, such as client entry and entires
1605 on channels this client may be on. */
1606 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1608 q->sock->user_data = NULL;
1610 /* Close the connection on our side */
1611 silc_server_close_connection(q->server, q->sock);
1613 silc_free(q->signoff);
1617 /* Quits SILC session. This is the normal way to disconnect client. */
1619 SILC_SERVER_CMD_FUNC(quit)
1621 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1622 SilcServer server = cmd->server;
1623 SilcSocketConnection sock = cmd->sock;
1625 unsigned char *tmp = NULL;
1626 unsigned int len = 0;
1628 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
1630 /* Get destination ID */
1631 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1635 q = silc_calloc(1, sizeof(*q));
1638 q->signoff = tmp ? strdup(tmp) : NULL;
1640 /* We quit the connection with little timeout */
1641 silc_task_register(server->timeout_queue, sock->sock,
1642 silc_server_command_quit_cb, (void *)q,
1643 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1645 silc_server_command_free(cmd);
1648 SILC_SERVER_CMD_FUNC(kill)
1652 /* Server side of command INFO. This sends information about us to
1653 the client. If client requested specific server we will send the
1654 command to that server. */
1656 SILC_SERVER_CMD_FUNC(info)
1658 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1659 SilcServer server = cmd->server;
1660 SilcBuffer packet, idp;
1661 char info_string[256], *dest_server;
1663 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1665 /* Get server name */
1666 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1669 SILC_STATUS_ERR_NO_SUCH_SERVER);
1673 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1674 /* Send our reply */
1675 memset(info_string, 0, sizeof(info_string));
1676 snprintf(info_string, sizeof(info_string),
1677 "location: %s server: %s admin: %s <%s>",
1678 server->config->admin_info->location,
1679 server->config->admin_info->server_type,
1680 server->config->admin_info->admin_name,
1681 server->config->admin_info->admin_email);
1683 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1685 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1686 SILC_STATUS_OK, 0, 2,
1687 2, idp->data, idp->len,
1689 strlen(info_string));
1690 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1691 packet->data, packet->len, FALSE);
1693 silc_buffer_free(packet);
1694 silc_buffer_free(idp);
1696 /* Send this command to the requested server */
1698 if (server->server_type == SILC_SERVER && !server->standalone) {
1702 if (server->server_type == SILC_ROUTER) {
1708 silc_server_command_free(cmd);
1711 /* Server side of command PING. This just replies to the ping. */
1713 SILC_SERVER_CMD_FUNC(ping)
1715 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1716 SilcServer server = cmd->server;
1721 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1724 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1726 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1727 SILC_STATUS_ERR_NO_SERVER_ID);
1730 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1734 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1735 /* Send our reply */
1736 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1739 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1740 SILC_STATUS_ERR_NO_SUCH_SERVER);
1747 silc_server_command_free(cmd);
1750 /* Assembles USERS command and executes it. This is called when client
1751 joins to a channel and we wan't to send USERS command reply to the
1754 void silc_server_command_send_users(SilcServer server,
1755 SilcSocketConnection sock,
1756 SilcChannelEntry channel,
1759 SilcServerCommandContext cmd;
1760 SilcBuffer buffer, idp;
1761 SilcPacketContext *packet = silc_packet_context_alloc();
1763 SILC_LOG_DEBUG(("Start"));
1765 /* Create USERS command packet and process it. */
1766 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1767 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1768 1, idp->data, idp->len);
1770 packet->buffer = silc_buffer_copy(buffer);
1771 packet->sock = sock;
1772 packet->type = SILC_PACKET_COMMAND;
1774 cmd = silc_server_command_alloc();
1775 cmd->payload = silc_command_payload_parse(buffer);
1776 if (!cmd->payload) {
1778 silc_buffer_free(buffer);
1779 silc_buffer_free(idp);
1780 silc_packet_context_free(packet);
1783 cmd->args = silc_command_get_args(cmd->payload);
1784 cmd->server = server;
1785 cmd->sock = silc_socket_dup(sock);
1786 cmd->packet = silc_packet_context_dup(packet);
1787 cmd->pending = FALSE;
1790 /* If this function was called from pending command then instead of
1791 processing the command now, register a pending command callback which
1792 will process it after we've received the automatic USERS command
1793 reply which server will send in JOIN. */
1794 silc_server_command_pending(server, SILC_COMMAND_USERS, 0, NULL,
1795 silc_server_command_users, cmd);
1796 cmd->pending = TRUE;
1797 silc_buffer_free(buffer);
1798 silc_buffer_free(idp);
1802 /* Process USERS command. */
1803 silc_server_command_users((void *)cmd);
1805 silc_buffer_free(buffer);
1806 silc_buffer_free(idp);
1807 silc_packet_context_free(packet);
1810 /* Internal routine to join channel. The channel sent to this function
1811 has been either created or resolved from ID lists. This joins the sent
1812 client to the channel. */
1814 static void silc_server_command_join_channel(SilcServer server,
1815 SilcServerCommandContext cmd,
1816 SilcChannelEntry channel,
1817 SilcClientID *client_id,
1821 SilcSocketConnection sock = cmd->sock;
1823 unsigned int tmp_len;
1824 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1825 SilcClientEntry client;
1826 SilcChannelClientEntry chl;
1827 SilcBuffer reply, chidp, clidp, keyp;
1828 unsigned short ident = silc_command_get_ident(cmd->payload);
1830 SILC_LOG_DEBUG(("Start"));
1835 /* Get passphrase */
1836 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1838 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1839 memcpy(passphrase, tmp, tmp_len);
1843 * Check channel modes
1846 /* Check invite list if channel is invite-only channel */
1847 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1848 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1849 /* Invite list is specified. Check whether client is invited in the
1850 list. If not, then check whether it has been invited otherwise. */
1853 /* XXX client must be invited to be able to join the channel */
1857 /* Check ban list if set */
1858 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1862 /* Check the channel passphrase if set. */
1863 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1864 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1865 strlen(channel->mode_data.passphrase))) {
1866 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1867 SILC_STATUS_ERR_BAD_PASSWORD);
1872 /* Check user count limit if set. */
1873 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1874 if (silc_list_count(channel->user_list) + 1 >
1875 channel->mode_data.user_limit) {
1876 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1877 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1883 * Client is allowed to join to the channel. Make it happen.
1886 /* Get the client entry */
1887 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1888 client = (SilcClientEntry)sock->user_data;
1890 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1893 /* XXX actually this is useless since router finds always cell's
1894 local clients from its local lists. */
1895 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1902 /* Check whether the client already is on the channel */
1903 if (silc_server_client_on_channel(client, channel)) {
1904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1905 SILC_STATUS_ERR_USER_ON_CHANNEL);
1909 /* Generate new channel key as protocol dictates */
1910 if ((!created && silc_list_count(channel->user_list) > 0) ||
1911 !channel->channel_key)
1912 silc_server_create_channel_key(server, channel, 0);
1914 /* Send the channel key. This is broadcasted to the channel but is not
1915 sent to the client who is joining to the channel. */
1916 silc_server_send_channel_key(server, NULL, channel,
1917 server->server_type == SILC_ROUTER ?
1918 FALSE : !server->standalone);
1920 /* Join the client to the channel by adding it to channel's user list.
1921 Add also the channel to client entry's channels list for fast cross-
1923 chl = silc_calloc(1, sizeof(*chl));
1925 chl->client = client;
1926 chl->channel = channel;
1927 silc_list_add(channel->user_list, chl);
1928 silc_list_add(client->channels, chl);
1930 /* Encode Client ID Payload of the original client who wants to join */
1931 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1933 /* Encode command reply packet */
1934 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1935 SILC_PUT32_MSB(channel->mode, mode);
1936 SILC_PUT32_MSB(created, tmp2);
1937 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1938 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1939 strlen(channel->channel_key->
1941 channel->channel_key->cipher->name,
1942 channel->key_len / 8, channel->key);
1944 if (!channel->topic) {
1946 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1947 SILC_STATUS_OK, ident, 5,
1948 2, channel->channel_name,
1949 strlen(channel->channel_name),
1950 3, chidp->data, chidp->len,
1953 6, keyp->data, keyp->len);
1956 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1957 SILC_STATUS_OK, ident, 6,
1958 2, channel->channel_name,
1959 strlen(channel->channel_name),
1960 3, chidp->data, chidp->len,
1963 6, keyp->data, keyp->len,
1965 strlen(channel->topic));
1968 /* Send command reply */
1969 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1970 reply->data, reply->len, FALSE);
1972 if (!cmd->pending) {
1973 /* Send JOIN notify to locally connected clients on the channel */
1974 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1975 SILC_NOTIFY_TYPE_JOIN, 2,
1976 clidp->data, clidp->len,
1977 chidp->data, chidp->len);
1979 /* Send JOIN notify packet to our primary router */
1980 if (!server->standalone)
1981 silc_server_send_notify_join(server, server->router->connection,
1982 server->server_type == SILC_ROUTER ?
1983 TRUE : FALSE, channel, client->id,
1984 SILC_ID_CLIENT_LEN);
1987 /* Send USERS command reply to the joined channel so the user sees who
1988 is currently on the channel. */
1989 silc_server_command_send_users(server, sock, channel, cmd->pending);
1991 silc_buffer_free(reply);
1992 silc_buffer_free(clidp);
1993 silc_buffer_free(chidp);
1994 silc_buffer_free(keyp);
1998 silc_free(passphrase);
2001 /* Server side of command JOIN. Joins client into requested channel. If
2002 the channel does not exist it will be created. */
2004 SILC_SERVER_CMD_FUNC(join)
2006 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2007 SilcServer server = cmd->server;
2009 char *tmp, *channel_name = NULL, *cipher, *hmac;
2010 SilcChannelEntry channel;
2011 unsigned int umode = 0;
2012 int created = FALSE;
2013 SilcClientID *client_id;
2015 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2017 /* Get channel name */
2018 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2021 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2026 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2027 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2028 SILC_STATUS_ERR_BAD_CHANNEL);
2029 silc_free(channel_name);
2033 /* Get Client ID of the client who is joining to the channel */
2034 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2037 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2040 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2043 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2047 /* Get cipher and hmac name */
2048 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2049 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2051 /* See if the channel exists */
2052 channel = silc_idlist_find_channel_by_name(server->local_list,
2053 channel_name, NULL);
2055 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2056 /* If this is coming from client the Client ID in the command packet must
2057 be same as the client's ID. */
2058 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2059 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2060 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2061 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2062 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2068 /* Channel not found */
2070 /* If we are standalone server we don't have a router, we just create
2071 the channel by ourselves. */
2072 if (server->standalone) {
2073 channel = silc_server_create_new_channel(server, server->id, cipher,
2074 hmac, channel_name, TRUE);
2075 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2080 /* The channel does not exist on our server. If we are normal server
2081 we will send JOIN command to our router which will handle the
2082 joining procedure (either creates the channel if it doesn't exist
2083 or joins the client to it). */
2084 if (server->server_type == SILC_SERVER) {
2086 unsigned short old_ident;
2088 old_ident = silc_command_get_ident(cmd->payload);
2089 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2090 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2092 /* Send JOIN command to our router */
2093 silc_server_packet_send(server, (SilcSocketConnection)
2094 server->router->connection,
2095 SILC_PACKET_COMMAND, cmd->packet->flags,
2096 tmpbuf->data, tmpbuf->len, TRUE);
2098 /* Reprocess this packet after received reply from router */
2099 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2100 silc_command_get_ident(cmd->payload),
2101 silc_server_command_destructor,
2102 silc_server_command_join,
2103 silc_server_command_dup(cmd));
2104 cmd->pending = TRUE;
2108 /* We are router and the channel does not seem exist so we will check
2109 our global list as well for the channel. */
2110 channel = silc_idlist_find_channel_by_name(server->global_list,
2111 channel_name, NULL);
2113 /* Channel really does not exist, create it */
2114 channel = silc_server_create_new_channel(server, server->id, cipher,
2115 hmac, channel_name, TRUE);
2116 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2123 /* Channel not found */
2125 /* If the command came from router and/or we are normal server then
2126 something went wrong with the joining as the channel was not found.
2127 We can't do anything else but ignore this. */
2128 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2129 server->server_type == SILC_SERVER)
2132 /* We are router and the channel does not seem exist so we will check
2133 our global list as well for the channel. */
2134 channel = silc_idlist_find_channel_by_name(server->global_list,
2135 channel_name, NULL);
2137 /* Channel really does not exist, create it */
2138 channel = silc_server_create_new_channel(server, server->id, cipher,
2139 hmac, channel_name, TRUE);
2140 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2146 /* If the channel does not have global users and is also empty it means the
2147 channel was created globally (by our router) and the client will be the
2148 channel founder and operator. */
2149 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2150 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2151 created = TRUE; /* Created globally by our router */
2154 /* Join to the channel */
2155 silc_server_command_join_channel(server, cmd, channel, client_id,
2158 silc_free(client_id);
2161 silc_server_command_free(cmd);
2164 /* Server side of command MOTD. Sends server's current "message of the
2165 day" to the client. */
2167 SILC_SERVER_CMD_FUNC(motd)
2169 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2170 SilcServer server = cmd->server;
2174 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2176 /* XXX show currently only our motd */
2178 if (server->config && server->config->motd &&
2179 server->config->motd->motd_file) {
2182 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2187 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2193 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2198 silc_server_command_free(cmd);
2201 SILC_SERVER_CMD_FUNC(umode)
2205 /* Checks that client has rights to add or remove channel modes. If any
2206 of the checks fails FALSE is returned. */
2208 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2209 SilcChannelClientEntry client,
2212 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2213 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2215 /* Check whether has rights to change anything */
2216 if (!is_op && !is_fo)
2219 /* Check whether has rights to change everything */
2223 /* We know that client is channel operator, check that they are not
2224 changing anything that requires channel founder rights. Rest of the
2225 modes are available automatically for channel operator. */
2227 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2228 if (is_op && !is_fo)
2231 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2232 if (is_op && !is_fo)
2237 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2238 if (is_op && !is_fo)
2241 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2242 if (is_op && !is_fo)
2247 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2248 if (is_op && !is_fo)
2251 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2252 if (is_op && !is_fo)
2260 /* Server side command of CMODE. Changes channel mode */
2262 SILC_SERVER_CMD_FUNC(cmode)
2264 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2265 SilcServer server = cmd->server;
2266 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2267 SilcChannelID *channel_id;
2268 SilcChannelEntry channel;
2269 SilcChannelClientEntry chl;
2270 SilcBuffer packet, cidp;
2271 unsigned char *tmp, *tmp_id, *tmp_mask;
2272 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2274 SILC_LOG_DEBUG(("Start"));
2276 argc = silc_argument_get_arg_num(cmd->args);
2278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2279 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2284 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2288 /* Get Channel ID */
2289 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2291 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2292 SILC_STATUS_ERR_NO_CHANNEL_ID);
2295 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2298 SILC_STATUS_ERR_NO_CHANNEL_ID);
2302 /* Get the channel mode mask */
2303 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2306 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2309 SILC_GET32_MSB(mode_mask, tmp_mask);
2311 /* Get channel entry */
2312 channel = silc_idlist_find_channel_by_id(server->local_list,
2315 channel = silc_idlist_find_channel_by_id(server->global_list,
2318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2319 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2324 /* Check whether this client is on the channel */
2325 if (!silc_server_client_on_channel(client, channel)) {
2326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2327 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2331 /* Get entry to the channel user list */
2332 silc_list_start(channel->user_list);
2333 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2334 if (chl->client == client)
2337 /* Check that client has rights to change any requested channel modes */
2338 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2340 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2345 * Check the modes. Modes that requires nothing special operation are
2349 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2350 /* Channel uses private keys to protect traffic. Client(s) has set the
2351 key locally they want to use, server does not know that key. */
2352 /* Nothing interesting to do here now */
2354 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2355 /* The mode is removed and we need to generate and distribute
2356 new channel key. Clients are not using private channel keys
2357 anymore after this. */
2359 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2362 /* Re-generate channel key */
2363 silc_server_create_channel_key(server, channel, 0);
2365 /* Encode channel key payload to be distributed on the channel */
2367 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2368 strlen(channel->channel_key->
2370 channel->channel_key->cipher->name,
2371 channel->key_len / 8, channel->key);
2373 /* If we are normal server then we will send it to our router. If we
2374 are router we will send it to all local servers that has clients on
2376 if (server->server_type == SILC_SERVER) {
2377 if (!server->standalone)
2378 silc_server_packet_send(server,
2379 cmd->server->router->connection,
2380 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2386 /* Send to locally connected clients on the channel */
2387 silc_server_packet_send_local_channel(server, channel,
2388 SILC_PACKET_CHANNEL_KEY, 0,
2389 packet->data, packet->len, FALSE);
2390 silc_buffer_free(packet);
2394 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2395 /* User limit is set on channel */
2396 unsigned int user_limit;
2398 /* Get user limit */
2399 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2401 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2403 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2407 SILC_GET32_MSB(user_limit, tmp);
2408 channel->mode_data.user_limit = user_limit;
2411 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2412 /* User limit mode is unset. Remove user limit */
2413 channel->mode_data.user_limit = 0;
2416 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2417 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2418 /* Passphrase has been set to channel */
2420 /* Get the passphrase */
2421 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2424 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2428 /* Save the passphrase */
2429 channel->mode_data.passphrase = strdup(tmp);
2432 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2433 /* Passphrase mode is unset. remove the passphrase */
2434 if (channel->mode_data.passphrase) {
2435 silc_free(channel->mode_data.passphrase);
2436 channel->mode_data.passphrase = NULL;
2441 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2442 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2443 /* Ban list is specified for channel */
2446 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2448 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2449 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2453 /* XXX check that channel founder is not banned */
2455 /* Save the ban list */
2456 channel->mode_data.ban_list = strdup(tmp);
2459 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2460 /* Ban mode is unset. Remove the entire ban list */
2461 if (channel->mode_data.ban_list) {
2462 silc_free(channel->mode_data.ban_list);
2463 channel->mode_data.ban_list = NULL;
2468 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2469 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2470 /* Invite list is specified for channel */
2472 /* Get invite list */
2473 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2475 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2476 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2480 /* Save the invite linst */
2481 channel->mode_data.invite_list = strdup(tmp);
2484 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2485 /* Invite list mode is unset. Remove the entire invite list */
2486 if (channel->mode_data.invite_list) {
2487 silc_free(channel->mode_data.invite_list);
2488 channel->mode_data.invite_list = NULL;
2493 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2494 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2495 /* Cipher to use protect the traffic */
2496 unsigned int key_len;
2499 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2502 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2506 /* XXX Duplicated code, make own function for this!! */
2508 /* Delete old cipher and allocate the new one */
2509 silc_cipher_free(channel->channel_key);
2510 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
2511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2512 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2515 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
2517 /* Re-generate channel key */
2518 silc_server_create_channel_key(server, channel, key_len);
2520 /* Encode channel key payload to be distributed on the channel */
2522 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2523 strlen(channel->channel_key->
2525 channel->channel_key->cipher->name,
2526 channel->key_len / 8, channel->key);
2528 /* If we are normal server then we will send it to our router. If we
2529 are router we will send it to all local servers that has clients on
2531 if (server->server_type == SILC_SERVER) {
2532 if (!server->standalone)
2533 silc_server_packet_send(server,
2534 cmd->server->router->connection,
2535 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2541 /* Send to locally connected clients on the channel */
2542 silc_server_packet_send_local_channel(server, channel,
2543 SILC_PACKET_CHANNEL_KEY, 0,
2544 packet->data, packet->len, FALSE);
2545 silc_buffer_free(packet);
2548 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2549 /* Cipher mode is unset. Remove the cipher and revert back to
2552 if (channel->mode_data.cipher) {
2553 silc_free(channel->mode_data.cipher);
2554 channel->mode_data.cipher = NULL;
2555 channel->mode_data.key_len = 0;
2558 /* Generate new cipher and key for the channel */
2560 /* XXX Duplicated code, make own function for this!! */
2562 /* Delete old cipher and allocate default one */
2563 silc_cipher_free(channel->channel_key);
2564 if (!channel->cipher)
2565 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
2567 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
2568 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2569 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2574 /* Re-generate channel key */
2575 silc_server_create_channel_key(server, channel, 0);
2577 /* Encode channel key payload to be distributed on the channel */
2579 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2580 strlen(channel->channel_key->
2582 channel->channel_key->cipher->name,
2583 channel->key_len / 8, channel->key);
2585 /* If we are normal server then we will send it to our router. If we
2586 are router we will send it to all local servers that has clients on
2588 if (server->server_type == SILC_SERVER) {
2589 if (!server->standalone)
2590 silc_server_packet_send(server,
2591 cmd->server->router->connection,
2592 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2598 /* Send to locally connected clients on the channel */
2599 silc_server_packet_send_local_channel(server, channel,
2600 SILC_PACKET_CHANNEL_KEY, 0,
2601 packet->data, packet->len, FALSE);
2602 silc_buffer_free(packet);
2606 /* Finally, set the mode */
2607 channel->mode = mode_mask;
2609 /* Send CMODE_CHANGE notify */
2610 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2611 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2612 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2613 cidp->data, cidp->len,
2616 /* Set CMODE notify type to network */
2617 if (!server->standalone)
2618 silc_server_send_notify_cmode(server, server->router->connection,
2619 server->server_type == SILC_ROUTER ?
2620 TRUE : FALSE, channel,
2621 mode_mask, client->id, SILC_ID_CLIENT_LEN);
2623 /* Send command reply to sender */
2624 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2625 SILC_STATUS_OK, 0, 1,
2627 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2628 packet->data, packet->len, FALSE);
2630 silc_buffer_free(packet);
2631 silc_free(channel_id);
2635 silc_server_command_free(cmd);
2638 /* Server side of CUMODE command. Changes client's mode on a channel. */
2640 SILC_SERVER_CMD_FUNC(cumode)
2642 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2643 SilcServer server = cmd->server;
2644 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2645 SilcChannelID *channel_id;
2646 SilcClientID *client_id;
2647 SilcChannelEntry channel;
2648 SilcClientEntry target_client;
2649 SilcChannelClientEntry chl;
2650 SilcBuffer packet, idp;
2651 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2652 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
2655 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2657 /* Get Channel ID */
2658 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2660 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2661 SILC_STATUS_ERR_NO_CHANNEL_ID);
2664 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
2666 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2667 SILC_STATUS_ERR_NO_CHANNEL_ID);
2671 /* Get channel entry */
2672 channel = silc_idlist_find_channel_by_id(server->local_list,
2675 channel = silc_idlist_find_channel_by_id(server->global_list,
2678 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2679 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2684 /* Check whether sender is on the channel */
2685 if (!silc_server_client_on_channel(client, channel)) {
2686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2687 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2691 /* Check that client has rights to change other's rights */
2692 silc_list_start(channel->user_list);
2693 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2694 if (chl->client == client) {
2695 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2696 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2697 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2698 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2702 sender_mask = chl->mode;
2707 /* Get the target client's channel mode mask */
2708 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2710 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2711 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2714 SILC_GET32_MSB(target_mask, tmp_mask);
2716 /* Get target Client ID */
2717 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2719 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2720 SILC_STATUS_ERR_NO_CLIENT_ID);
2723 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2725 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2726 SILC_STATUS_ERR_NO_CLIENT_ID);
2730 /* Get target client's entry */
2731 target_client = silc_idlist_find_client_by_id(server->local_list,
2733 if (!target_client) {
2734 target_client = silc_idlist_find_client_by_id(server->global_list,
2738 /* Check whether target client is on the channel */
2739 if (!silc_server_client_on_channel(target_client, channel)) {
2740 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2741 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2745 /* Get entry to the channel user list */
2746 silc_list_start(channel->user_list);
2747 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2748 if (chl->client == target_client)
2755 /* If the target client is founder, no one else can change their mode
2757 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2758 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2759 SILC_STATUS_ERR_NOT_YOU);
2763 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2764 /* Cannot promote anyone to channel founder */
2765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2766 SILC_STATUS_ERR_NOT_YOU);
2769 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2770 if (target_client == client) {
2771 /* Remove channel founder rights from itself */
2772 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2776 SILC_STATUS_ERR_NOT_YOU);
2782 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2783 /* Promote to operator */
2784 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2785 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2789 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2790 /* Demote to normal user */
2791 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2796 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2798 /* Send notify to channel, notify only if mode was actually changed. */
2800 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2801 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2802 idp->data, idp->len,
2806 /* Set CUMODE notify type to network */
2807 if (!server->standalone)
2808 silc_server_send_notify_cumode(server, server->router->connection,
2809 server->server_type == SILC_ROUTER ?
2810 TRUE : FALSE, channel,
2811 target_mask, client->id,
2814 SILC_ID_CLIENT_LEN);
2817 /* Send command reply to sender */
2818 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2819 SILC_STATUS_OK, 0, 2,
2821 3, tmp_id, tmp_len);
2822 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2823 packet->data, packet->len, FALSE);
2825 silc_buffer_free(packet);
2826 silc_free(channel_id);
2827 silc_free(client_id);
2828 silc_buffer_free(idp);
2831 silc_server_command_free(cmd);
2834 /* Server side of KICK command. Kicks client out of channel. */
2836 SILC_SERVER_CMD_FUNC(kick)
2838 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2839 SilcServer server = cmd->server;
2840 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2841 SilcClientEntry target_client;
2842 SilcChannelID *channel_id;
2843 SilcClientID *client_id;
2844 SilcChannelEntry channel;
2845 SilcChannelClientEntry chl;
2847 unsigned int tmp_len;
2848 unsigned char *tmp, *comment;
2850 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
2852 /* Get Channel ID */
2853 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2855 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2856 SILC_STATUS_ERR_NO_CHANNEL_ID);
2859 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2862 SILC_STATUS_ERR_NO_CHANNEL_ID);
2866 /* Get channel entry */
2867 channel = silc_idlist_find_channel_by_id(server->local_list,
2870 channel = silc_idlist_find_channel_by_id(server->local_list,
2873 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2874 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2879 /* Check whether sender is on the channel */
2880 if (!silc_server_client_on_channel(client, channel)) {
2881 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2882 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2886 /* Check that the kicker is channel operator or channel founder */
2887 silc_list_start(channel->user_list);
2888 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2889 if (chl->client == client) {
2890 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2891 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2892 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2899 /* Get target Client ID */
2900 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2902 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2903 SILC_STATUS_ERR_NO_CLIENT_ID);
2906 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2908 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2909 SILC_STATUS_ERR_NO_CLIENT_ID);
2913 /* Get target client's entry */
2914 target_client = silc_idlist_find_client_by_id(server->local_list,
2916 if (!target_client) {
2917 target_client = silc_idlist_find_client_by_id(server->global_list,
2921 /* Check that the target client is not channel founder. Channel founder
2922 cannot be kicked from the channel. */
2923 silc_list_start(channel->user_list);
2924 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2925 if (chl->client == target_client) {
2926 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2927 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2928 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
2935 /* Check whether target client is on the channel */
2936 if (!silc_server_client_on_channel(target_client, channel)) {
2937 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2938 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2944 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2948 /* Send command reply to sender */
2949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2952 /* Send KICKED notify to local clients on the channel */
2953 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
2954 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2955 SILC_NOTIFY_TYPE_KICKED,
2957 idp->data, idp->len,
2958 comment, comment ? strlen(comment) : 0);
2959 silc_buffer_free(idp);
2961 /* Remove the client from the channel. If the channel does not exist
2962 after removing the client then the client kicked itself of the channel
2963 and we don't have to send anything after that. */
2964 if (!silc_server_remove_from_one_channel(server, NULL, channel,
2965 target_client, FALSE))
2968 /* Send KICKED notify to primary route */
2969 if (!server->standalone)
2970 silc_server_send_notify_kicked(server, server->router->connection,
2971 server->server_type == SILC_ROUTER ?
2972 TRUE : FALSE, channel,
2973 target_client->id, SILC_ID_CLIENT_LEN,
2976 /* Re-generate channel key */
2977 silc_server_create_channel_key(server, channel, 0);
2979 /* Send the channel key to the channel. The key of course is not sent
2980 to the client who joined the channel. */
2981 silc_server_send_channel_key(server, target_client->connection, channel,
2982 server->server_type == SILC_ROUTER ?
2983 FALSE : !server->standalone);
2986 silc_server_command_free(cmd);
2989 SILC_SERVER_CMD_FUNC(oper)
2993 SILC_SERVER_CMD_FUNC(silcoper)
2997 /* Server side command of CONNECT. Connects us to the specified remote
2998 server or router. */
3000 SILC_SERVER_CMD_FUNC(connect)
3002 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3003 SilcServer server = cmd->server;
3004 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3006 unsigned int tmp_len;
3007 unsigned int port = SILC_PORT;
3009 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
3011 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3014 /* Check whether client has the permissions. */
3015 if (client->mode == SILC_UMODE_NONE) {
3016 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3017 SILC_STATUS_ERR_NO_SERVER_PRIV);
3021 if (server->server_type == SILC_ROUTER &&
3022 client->mode & SILC_UMODE_SERVER_OPERATOR) {
3023 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3024 SILC_STATUS_ERR_NO_ROUTER_PRIV);
3028 /* Get the remote server */
3029 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3031 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3032 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3037 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3039 SILC_GET32_MSB(port, tmp);
3041 /* Create the connection. It is done with timeout and is async. */
3042 silc_server_create_connection(server, tmp, port);
3044 /* Send reply to the sender */
3045 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3049 silc_server_command_free(cmd);
3052 SILC_SERVER_CMD_FUNC(restart)
3056 /* Server side command of CLOSE. Closes connection to a specified server. */
3058 SILC_SERVER_CMD_FUNC(close)
3060 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3061 SilcServer server = cmd->server;
3062 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3063 SilcServerEntry server_entry;
3065 unsigned int tmp_len;
3066 unsigned char *name;
3067 unsigned int port = SILC_PORT;
3069 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3071 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3074 /* Check whether client has the permissions. */
3075 if (client->mode == SILC_UMODE_NONE) {
3076 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3077 SILC_STATUS_ERR_NO_SERVER_PRIV);
3081 /* Get the remote server */
3082 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3084 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3085 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3090 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3092 SILC_GET32_MSB(port, tmp);
3094 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3096 if (!server_entry) {
3097 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3098 SILC_STATUS_ERR_NO_SERVER_ID);
3102 /* Close the connection to the server */
3103 silc_server_free_sock_user_data(server, server_entry->connection);
3104 silc_server_disconnect_remote(server, server_entry->connection,
3105 "Server closed connection: "
3106 "Closed by operator");
3108 /* Send reply to the sender */
3109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3113 silc_server_command_free(cmd);
3116 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3117 active connections. */
3119 SILC_SERVER_CMD_FUNC(shutdown)
3121 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3122 SilcServer server = cmd->server;
3123 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3125 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3127 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3130 /* Check whether client has the permission. */
3131 if (client->mode == SILC_UMODE_NONE) {
3132 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3133 SILC_STATUS_ERR_NO_SERVER_PRIV);
3137 /* Then, gracefully, or not, bring the server down. */
3138 silc_server_stop(server);
3140 /* Send reply to the sender */
3141 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3145 silc_server_command_free(cmd);
3148 /* Server side command of LEAVE. Removes client from a channel. */
3150 SILC_SERVER_CMD_FUNC(leave)
3152 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3153 SilcServer server = cmd->server;
3154 SilcSocketConnection sock = cmd->sock;
3155 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3157 SilcChannelEntry channel;
3159 unsigned int i, len;
3162 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3164 /* Get Channel ID */
3165 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3168 SILC_STATUS_ERR_NO_CHANNEL_ID);
3171 id = silc_id_payload_parse_id(tmp, len);
3173 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3174 SILC_STATUS_ERR_NO_CHANNEL_ID);
3178 /* Get channel entry */
3179 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3181 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3184 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3189 /* Check whether this client is on the channel */
3190 if (!silc_server_client_on_channel(id_entry, channel)) {
3191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3192 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3196 /* Notify routers that they should remove this client from their list
3197 of clients on the channel. Send LEAVE notify type. */
3198 if (!server->standalone)
3199 silc_server_send_notify_leave(server, server->router->connection,
3200 server->server_type == SILC_ROUTER ?
3201 TRUE : FALSE, channel, id_entry->id,
3202 SILC_ID_CLIENT_LEN);
3204 /* Remove client from channel */
3205 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3207 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3210 /* If the channel does not exist anymore we won't send anything */
3214 /* Re-generate channel key */
3215 silc_server_create_channel_key(server, channel, 0);
3217 /* Encode channel key payload to be distributed on the channel */
3219 silc_channel_key_payload_encode(len, tmp,
3220 strlen(channel->channel_key->cipher->name),
3221 channel->channel_key->cipher->name,
3222 channel->key_len / 8, channel->key);
3224 /* If we are normal server then we will send it to our router. If we
3225 are router we will send it to all local servers that has clients on
3227 if (server->server_type == SILC_SERVER) {
3228 if (!server->standalone)
3229 silc_server_packet_send(server,
3230 cmd->server->router->connection,
3231 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3232 packet->len, FALSE);
3237 /* Send to locally connected clients on the channel */
3238 silc_server_packet_send_local_channel(server, channel,
3239 SILC_PACKET_CHANNEL_KEY, 0,
3240 packet->data, packet->len, FALSE);
3242 silc_buffer_free(packet);
3246 silc_server_command_free(cmd);
3249 /* Server side of command USERS. Resolves clients and their USERS currently
3250 joined on the requested channel. The list of Client ID's and their modes
3251 on the channel is sent back. */
3253 SILC_SERVER_CMD_FUNC(users)
3255 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3256 SilcServer server = cmd->server;
3257 SilcChannelEntry channel;
3258 SilcChannelClientEntry chl;
3261 unsigned char *channel_id;
3262 unsigned int channel_id_len;
3263 SilcBuffer client_id_list;
3264 SilcBuffer client_mode_list;
3266 unsigned char lc[4];
3267 unsigned int list_count = 0;
3268 unsigned short ident = silc_command_get_ident(cmd->payload);
3270 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3272 /* Get Channel ID */
3273 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3276 SILC_STATUS_ERR_NO_CHANNEL_ID);
3279 id = silc_id_payload_parse_id(channel_id, channel_id_len);
3281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3282 SILC_STATUS_ERR_NO_CHANNEL_ID);
3286 /* If we are server and we don't know about this channel we will send
3287 the command to our router. If we know about the channel then we also
3288 have the list of users already. */
3289 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3291 if (server->server_type == SILC_SERVER && !server->standalone &&
3295 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3296 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3298 /* Send USERS command */
3299 silc_server_packet_send(server, server->router->connection,
3300 SILC_PACKET_COMMAND, cmd->packet->flags,
3301 tmpbuf->data, tmpbuf->len, TRUE);
3303 /* Reprocess this packet after received reply */
3304 silc_server_command_pending(server, SILC_COMMAND_USERS,
3305 silc_command_get_ident(cmd->payload),
3306 silc_server_command_destructor,
3307 silc_server_command_users,
3308 silc_server_command_dup(cmd));
3309 cmd->pending = TRUE;
3310 silc_command_set_ident(cmd->payload, ident);
3312 silc_buffer_free(tmpbuf);
3317 /* We are router and we will check the global list as well. */
3318 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3320 /* Channel really does not exist */
3321 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3322 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3327 /* Assemble the lists now */
3329 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
3330 silc_list_count(channel->user_list));
3331 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
3333 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
3334 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
3336 silc_list_start(channel->user_list);
3337 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3339 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
3340 silc_buffer_put(client_id_list, idp->data, idp->len);
3341 silc_buffer_pull(client_id_list, idp->len);
3342 silc_buffer_free(idp);
3344 /* Client's mode on channel */
3345 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
3346 silc_buffer_pull(client_mode_list, 4);
3350 silc_buffer_push(client_id_list,
3351 client_id_list->data - client_id_list->head);
3352 silc_buffer_push(client_mode_list,
3353 client_mode_list->data - client_mode_list->head);
3356 SILC_PUT32_MSB(list_count, lc);
3359 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3360 SILC_STATUS_OK, 0, 4,
3361 2, channel_id, channel_id_len,
3363 4, client_id_list->data,
3364 client_id_list->len,
3365 5, client_mode_list->data,
3366 client_mode_list->len);
3367 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3368 packet->data, packet->len, FALSE);
3370 silc_buffer_free(packet);
3371 silc_buffer_free(client_id_list);
3372 silc_buffer_free(client_mode_list);
3376 silc_server_command_free(cmd);