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);
547 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
549 2, idp->data, idp->len,
553 strlen(entry->userinfo),
557 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
559 2, idp->data, idp->len,
565 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
566 0, packet->data, packet->len, FALSE);
568 silc_buffer_free(packet);
569 silc_buffer_free(idp);
574 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
576 SilcServer server = cmd->server;
577 char *nick = NULL, *server_name = NULL;
578 int count = 0, clients_count = 0;
579 SilcClientEntry *clients = NULL, entry;
580 SilcClientID **client_id = NULL;
581 unsigned int client_id_count = 0;
584 /* Protocol dictates that we must always send the received WHOIS request
585 to our router if we are normal server, so let's do it now unless we
586 are standalone. We will not send any replies to the client until we
587 have received reply from the router. */
588 if (server->server_type == SILC_SERVER &&
589 !cmd->pending && !server->standalone) {
591 unsigned short old_ident;
593 old_ident = silc_command_get_ident(cmd->payload);
594 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
595 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
597 /* Send WHOIS command to our router */
598 silc_server_packet_send(server, (SilcSocketConnection)
599 server->router->connection,
600 SILC_PACKET_COMMAND, cmd->packet->flags,
601 tmpbuf->data, tmpbuf->len, TRUE);
603 /* Reprocess this packet after received reply from router */
604 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
605 silc_command_get_ident(cmd->payload),
606 silc_server_command_destructor,
607 silc_server_command_whois,
608 silc_server_command_dup(cmd));
611 silc_command_set_ident(cmd->payload, old_ident);
613 silc_buffer_free(tmpbuf);
618 /* We are ready to process the command request. Let's search for the
619 requested client and send reply to the requesting client. */
621 /* Parse the whois request */
622 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
623 &nick, &server_name, &count,
627 /* Get all clients matching that ID or nickname from local list */
628 if (client_id_count) {
629 /* Check all Client ID's received in the command packet */
630 for (i = 0; i < client_id_count; i++) {
631 entry = silc_idlist_find_client_by_id(server->local_list,
634 clients = silc_realloc(clients, sizeof(*clients) *
635 (clients_count + 1));
636 clients[clients_count++] = entry;
640 clients = silc_idlist_get_clients_by_nickname(server->local_list,
645 /* Check global list as well */
647 if (client_id_count) {
648 /* Check all Client ID's received in the command packet */
649 for (i = 0; i < client_id_count; i++) {
650 entry = silc_idlist_find_client_by_id(server->global_list,
653 clients = silc_realloc(clients, sizeof(*clients) *
654 (clients_count + 1));
655 clients[clients_count++] = entry;
659 clients = silc_idlist_get_clients_by_nickname(server->global_list,
666 /* Such client(s) really does not exist in the SILC network. */
667 if (!client_id_count) {
668 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
669 SILC_STATUS_ERR_NO_SUCH_NICK,
670 3, nick, strlen(nick));
672 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
673 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
674 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
675 2, idp->data, idp->len);
676 silc_buffer_free(idp);
681 /* Router always finds the client entry if it exists in the SILC network.
682 However, it might be incomplete entry and does not include all the
683 mandatory fields that WHOIS command reply requires. Check for these and
684 make query from the server who owns the client if some fields are
686 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
691 /* Send the command reply to the client */
692 silc_server_command_whois_send_reply(cmd, clients, clients_count);
695 if (client_id_count) {
696 for (i = 0; i < client_id_count; i++)
697 silc_free(client_id[i]);
698 silc_free(client_id);
705 silc_free(server_name);
711 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
713 SilcServer server = cmd->server;
714 char *nick = NULL, *server_name = NULL;
715 int count = 0, clients_count = 0;
716 SilcClientEntry *clients = NULL, entry;
717 SilcClientID **client_id = NULL;
718 unsigned int client_id_count = 0;
721 /* Parse the whois request */
722 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
723 &nick, &server_name, &count,
727 /* Process the command request. Let's search for the requested client and
728 send reply to the requesting server. */
730 if (client_id_count) {
731 /* Check all Client ID's received in the command packet */
732 for (i = 0; i < client_id_count; i++) {
733 entry = silc_idlist_find_client_by_id(server->local_list,
736 clients = silc_realloc(clients, sizeof(*clients) *
737 (clients_count + 1));
738 clients[clients_count++] = entry;
742 clients = silc_idlist_get_clients_by_nickname(server->local_list,
746 clients = silc_idlist_get_clients_by_hash(server->local_list,
747 nick, server->md5hash,
751 /* If we are router we will check our global list as well. */
752 if (!clients && server->server_type == SILC_ROUTER) {
753 if (client_id_count) {
754 /* Check all Client ID's received in the command packet */
755 for (i = 0; i < client_id_count; i++) {
756 entry = silc_idlist_find_client_by_id(server->global_list,
759 clients = silc_realloc(clients, sizeof(*clients) *
760 (clients_count + 1));
761 clients[clients_count++] = entry;
765 clients = silc_idlist_get_clients_by_nickname(server->global_list,
769 clients = silc_idlist_get_clients_by_hash(server->global_list,
770 nick, server->md5hash,
776 /* Such a client really does not exist in the SILC network. */
777 if (!client_id_count) {
778 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
779 SILC_STATUS_ERR_NO_SUCH_NICK,
780 3, nick, strlen(nick));
782 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
783 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
784 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
785 2, idp->data, idp->len);
786 silc_buffer_free(idp);
791 /* Router always finds the client entry if it exists in the SILC network.
792 However, it might be incomplete entry and does not include all the
793 mandatory fields that WHOIS command reply requires. Check for these and
794 make query from the server who owns the client if some fields are
796 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
801 /* Send the command reply to the client */
802 silc_server_command_whois_send_reply(cmd, clients, clients_count);
805 if (client_id_count) {
806 for (i = 0; i < client_id_count; i++)
807 silc_free(client_id[i]);
808 silc_free(client_id);
815 silc_free(server_name);
820 /* Server side of command WHOIS. Processes user's query and sends found
821 results as command replies back to the client. */
823 SILC_SERVER_CMD_FUNC(whois)
825 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
828 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
830 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
831 ret = silc_server_command_whois_from_client(cmd);
832 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
833 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
834 ret = silc_server_command_whois_from_server(cmd);
837 silc_server_command_free(cmd);
840 SILC_SERVER_CMD_FUNC(whowas)
844 /******************************************************************************
848 ******************************************************************************/
850 /* Checks that all mandatory fields are present. If not then send WHOIS
851 request to the server who owns the client. We use WHOIS because we want
852 to get as much information as possible at once. */
855 silc_server_command_identify_check(SilcServerCommandContext cmd,
856 SilcClientEntry *clients,
857 unsigned int clients_count)
859 SilcServer server = cmd->server;
861 SilcClientEntry entry;
863 for (i = 0; i < clients_count; i++) {
866 if (!entry->nickname) {
868 unsigned short old_ident;
873 old_ident = silc_command_get_ident(cmd->payload);
874 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
875 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
876 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
878 /* Send WHOIS request. We send WHOIS since we're doing the requesting
879 now anyway so make it a good one. */
880 silc_server_packet_send(server, entry->router->connection,
881 SILC_PACKET_COMMAND, cmd->packet->flags,
882 tmpbuf->data, tmpbuf->len, TRUE);
884 /* Reprocess this packet after received reply */
885 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
886 silc_command_get_ident(cmd->payload),
887 silc_server_command_destructor,
888 silc_server_command_identify,
889 silc_server_command_dup(cmd));
893 /* Put old data back to the Command Payload we just changed */
894 silc_command_set_ident(cmd->payload, old_ident);
895 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
897 silc_buffer_free(tmpbuf);
906 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
907 SilcClientEntry *clients,
908 unsigned int clients_count)
910 SilcServer server = cmd->server;
912 int i, count = 0, len;
913 SilcBuffer packet, idp;
914 SilcClientEntry entry;
915 SilcCommandStatus status;
916 unsigned short ident = silc_command_get_ident(cmd->payload);
918 status = SILC_STATUS_OK;
919 if (clients_count > 1)
920 status = SILC_STATUS_LIST_START;
922 for (i = 0; i < clients_count; i++) {
925 if (count && i - 1 == count)
928 if (clients_count > 2)
929 status = SILC_STATUS_LIST_ITEM;
931 if (clients_count > 1 && i == clients_count - 1)
932 status = SILC_STATUS_LIST_END;
934 /* Send IDENTIFY reply */
935 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
936 tmp = silc_argument_get_first_arg(cmd->args, NULL);
940 char nh[256], uh[256];
941 SilcSocketConnection hsock;
943 memset(uh, 0, sizeof(uh));
944 memset(nh, 0, sizeof(nh));
946 strncat(nh, entry->nickname, strlen(entry->nickname));
947 if (!strchr(entry->nickname, '@')) {
949 len = entry->router ? strlen(entry->router->server_name) :
950 strlen(server->server_name);
951 strncat(nh, entry->router ? entry->router->server_name :
952 server->server_name, len);
955 if (!entry->username) {
956 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
957 SILC_STATUS_OK, ident, 2,
958 2, idp->data, idp->len,
961 strncat(uh, entry->username, strlen(entry->username));
962 if (!strchr(entry->username, '@')) {
964 hsock = (SilcSocketConnection)entry->connection;
965 len = strlen(hsock->hostname);
966 strncat(uh, hsock->hostname, len);
969 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
970 SILC_STATUS_OK, ident, 3,
971 2, idp->data, idp->len,
976 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
977 0, packet->data, packet->len, FALSE);
979 silc_buffer_free(packet);
980 silc_buffer_free(idp);
986 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
988 SilcServer server = cmd->server;
989 char *nick = NULL, *server_name = NULL;
990 int count = 0, clients_count = 0;
991 SilcClientEntry *clients = NULL, entry;
992 SilcClientID **client_id = NULL;
993 unsigned int client_id_count = 0;
996 /* Protocol dictates that we must always send the received IDENTIFY request
997 to our router if we are normal server, so let's do it now unless we
998 are standalone. We will not send any replies to the client until we
999 have received reply from the router. */
1000 if (server->server_type == SILC_SERVER &&
1001 !cmd->pending && !server->standalone) {
1003 unsigned short old_ident;
1005 old_ident = silc_command_get_ident(cmd->payload);
1006 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1007 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1009 /* Send IDENTIFY command to our router */
1010 silc_server_packet_send(server, (SilcSocketConnection)
1011 server->router->connection,
1012 SILC_PACKET_COMMAND, cmd->packet->flags,
1013 tmpbuf->data, tmpbuf->len, TRUE);
1015 /* Reprocess this packet after received reply from router */
1016 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1017 silc_command_get_ident(cmd->payload),
1018 silc_server_command_destructor,
1019 silc_server_command_identify,
1020 silc_server_command_dup(cmd));
1021 cmd->pending = TRUE;
1023 silc_command_set_ident(cmd->payload, old_ident);
1025 silc_buffer_free(tmpbuf);
1030 /* We are ready to process the command request. Let's search for the
1031 requested client and send reply to the requesting client. */
1033 /* Parse the IDENTIFY request */
1034 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1035 &nick, &server_name, &count,
1036 SILC_COMMAND_IDENTIFY))
1039 /* Get all clients matching that ID or nickname from local list */
1040 if (client_id_count) {
1041 /* Check all Client ID's received in the command packet */
1042 for (i = 0; i < client_id_count; i++) {
1043 entry = silc_idlist_find_client_by_id(server->local_list,
1044 client_id[i], NULL);
1046 clients = silc_realloc(clients, sizeof(*clients) *
1047 (clients_count + 1));
1048 clients[clients_count++] = entry;
1052 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1057 /* Check global list as well */
1059 if (client_id_count) {
1060 /* Check all Client ID's received in the command packet */
1061 for (i = 0; i < client_id_count; i++) {
1062 entry = silc_idlist_find_client_by_id(server->global_list,
1063 client_id[i], NULL);
1065 clients = silc_realloc(clients, sizeof(*clients) *
1066 (clients_count + 1));
1067 clients[clients_count++] = entry;
1071 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1078 /* Such a client really does not exist in the SILC network. */
1079 if (!client_id_count) {
1080 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1081 SILC_STATUS_ERR_NO_SUCH_NICK,
1082 3, nick, strlen(nick));
1084 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1085 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1086 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1087 2, idp->data, idp->len);
1088 silc_buffer_free(idp);
1093 /* Check that all mandatory fields are present and request those data
1094 from the server who owns the client if necessary. */
1095 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1100 /* Send the command reply to the client */
1101 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1104 if (client_id_count) {
1105 for (i = 0; i < client_id_count; i++)
1106 silc_free(client_id[i]);
1107 silc_free(client_id);
1114 silc_free(server_name);
1120 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1122 SilcServer server = cmd->server;
1123 char *nick = NULL, *server_name = NULL;
1124 int count = 0, clients_count = 0;
1125 SilcClientEntry *clients = NULL, entry;
1126 SilcClientID **client_id = NULL;
1127 unsigned int client_id_count = 0;
1130 /* Parse the IDENTIFY request */
1131 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1132 &nick, &server_name, &count,
1133 SILC_COMMAND_IDENTIFY))
1136 /* Process the command request. Let's search for the requested client and
1137 send reply to the requesting server. */
1139 if (client_id_count) {
1140 /* Check all Client ID's received in the command packet */
1141 for (i = 0; i < client_id_count; i++) {
1142 entry = silc_idlist_find_client_by_id(server->local_list,
1143 client_id[i], NULL);
1145 clients = silc_realloc(clients, sizeof(*clients) *
1146 (clients_count + 1));
1147 clients[clients_count++] = entry;
1151 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1155 clients = silc_idlist_get_clients_by_hash(server->local_list,
1156 nick, server->md5hash,
1160 /* If we are router we will check our global list as well. */
1161 if (!clients && server->server_type == SILC_ROUTER) {
1162 if (client_id_count) {
1163 /* Check all Client ID's received in the command packet */
1164 for (i = 0; i < client_id_count; i++) {
1165 entry = silc_idlist_find_client_by_id(server->global_list,
1166 client_id[i], NULL);
1168 clients = silc_realloc(clients, sizeof(*clients) *
1169 (clients_count + 1));
1170 clients[clients_count++] = entry;
1174 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1178 clients = silc_idlist_get_clients_by_hash(server->global_list,
1179 nick, server->md5hash,
1185 /* Such a client really does not exist in the SILC network. */
1186 if (!client_id_count) {
1187 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1188 SILC_STATUS_ERR_NO_SUCH_NICK,
1189 3, nick, strlen(nick));
1191 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1192 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1193 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1194 2, idp->data, idp->len);
1195 silc_buffer_free(idp);
1200 /* Check that all mandatory fields are present and request those data
1201 from the server who owns the client if necessary. */
1202 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1207 /* Send the command reply */
1208 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1211 if (client_id_count) {
1212 for (i = 0; i < client_id_count; i++)
1213 silc_free(client_id[i]);
1214 silc_free(client_id);
1221 silc_free(server_name);
1226 SILC_SERVER_CMD_FUNC(identify)
1228 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1231 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1233 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1234 ret = silc_server_command_identify_from_client(cmd);
1235 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1236 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1237 ret = silc_server_command_identify_from_server(cmd);
1240 silc_server_command_free(cmd);
1243 /* Checks string for bad characters and returns TRUE if they are found. */
1245 static int silc_server_command_bad_chars(char *nick)
1247 if (strchr(nick, '\\')) return TRUE;
1248 if (strchr(nick, '\"')) return TRUE;
1249 if (strchr(nick, '´')) return TRUE;
1250 if (strchr(nick, '`')) return TRUE;
1251 if (strchr(nick, '\'')) return TRUE;
1252 if (strchr(nick, '*')) return TRUE;
1253 if (strchr(nick, '/')) return TRUE;
1254 if (strchr(nick, '@')) return TRUE;
1259 /* Server side of command NICK. Sets nickname for user. Setting
1260 nickname causes generation of a new client ID for the client. The
1261 new client ID is sent to the client after changing the nickname. */
1263 SILC_SERVER_CMD_FUNC(nick)
1265 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1266 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1267 SilcServer server = cmd->server;
1268 SilcBuffer packet, nidp, oidp;
1269 SilcClientID *new_id;
1272 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1274 /* Check nickname */
1275 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1276 if (silc_server_command_bad_chars(nick) == TRUE) {
1277 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1278 SILC_STATUS_ERR_BAD_NICKNAME);
1282 /* Create new Client ID */
1283 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1284 cmd->server->md5hash, nick,
1287 /* Send notify about nickname change to our router. We send the new
1288 ID and ask to replace it with the old one. If we are router the
1289 packet is broadcasted. Send NICK_CHANGE notify. */
1290 if (!server->standalone)
1291 silc_server_send_notify_nick_change(server, server->router->connection,
1292 server->server_type == SILC_SERVER ?
1293 FALSE : TRUE, client->id,
1294 new_id, SILC_ID_CLIENT_LEN);
1296 /* Remove old cache entry */
1297 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1300 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1304 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1305 silc_free(client->id);
1308 /* Save the nickname as this client is our local client */
1309 if (client->nickname)
1310 silc_free(client->nickname);
1312 client->nickname = strdup(nick);
1313 client->id = new_id;
1315 /* Update client cache */
1316 silc_idcache_add(server->local_list->clients, client->nickname,
1317 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1319 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1321 /* Send NICK_CHANGE notify to the client's channels */
1322 silc_server_send_notify_on_channels(server, client,
1323 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1324 oidp->data, oidp->len,
1325 nidp->data, nidp->len);
1327 /* Send the new Client ID as reply command back to client */
1328 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1329 SILC_STATUS_OK, 0, 1,
1330 2, nidp->data, nidp->len);
1331 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1332 0, packet->data, packet->len, FALSE);
1334 silc_buffer_free(packet);
1335 silc_buffer_free(nidp);
1336 silc_buffer_free(oidp);
1339 silc_server_command_free(cmd);
1342 SILC_SERVER_CMD_FUNC(list)
1346 /* Server side of TOPIC command. Sets topic for channel and/or returns
1347 current topic to client. */
1349 SILC_SERVER_CMD_FUNC(topic)
1351 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1352 SilcServer server = cmd->server;
1353 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1354 SilcChannelID *channel_id;
1355 SilcChannelEntry channel;
1356 SilcChannelClientEntry chl;
1357 SilcBuffer packet, idp;
1359 unsigned int argc, tmp_len;
1361 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1363 argc = silc_argument_get_arg_num(cmd->args);
1365 /* Get Channel ID */
1366 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1369 SILC_STATUS_ERR_NO_CHANNEL_ID);
1372 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1375 SILC_STATUS_ERR_NO_CHANNEL_ID);
1379 /* Check whether the channel exists */
1380 channel = silc_idlist_find_channel_by_id(server->local_list,
1383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1384 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1390 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1393 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1397 if (strlen(tmp) > 256) {
1398 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1399 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1403 /* See whether has rights to change topic */
1404 silc_list_start(channel->user_list);
1405 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1406 if (chl->client == client)
1409 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1410 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1411 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1412 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1417 /* Set the topic for channel */
1419 silc_free(channel->topic);
1420 channel->topic = strdup(tmp);
1422 /* Send TOPIC_SET notify type to the network */
1423 if (!server->standalone)
1424 silc_server_send_notify_topic_set(server, server->router->connection,
1425 server->server_type == SILC_ROUTER ?
1426 TRUE : FALSE, channel, client->id,
1427 SILC_ID_CLIENT_LEN, channel->topic);
1429 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1431 /* Send notify about topic change to all clients on the channel */
1432 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1433 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1434 idp->data, idp->len,
1435 channel->topic, strlen(channel->topic));
1436 silc_buffer_free(idp);
1439 /* Send the topic to client as reply packet */
1440 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1442 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1443 SILC_STATUS_OK, 0, 2,
1444 2, idp->data, idp->len,
1446 strlen(channel->topic));
1448 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1449 SILC_STATUS_OK, 0, 1,
1450 2, idp->data, idp->len);
1451 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1452 0, packet->data, packet->len, FALSE);
1454 silc_buffer_free(packet);
1455 silc_buffer_free(idp);
1456 silc_free(channel_id);
1459 silc_server_command_free(cmd);
1462 /* Server side of INVITE command. Invites some client to join some channel. */
1464 SILC_SERVER_CMD_FUNC(invite)
1466 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1467 SilcServer server = cmd->server;
1468 SilcSocketConnection sock = cmd->sock, dest_sock;
1469 SilcClientEntry sender, dest;
1470 SilcClientID *dest_id;
1471 SilcChannelEntry channel;
1472 SilcChannelID *channel_id;
1477 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1479 /* Get destination ID */
1480 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1483 SILC_STATUS_ERR_NO_CLIENT_ID);
1486 dest_id = silc_id_payload_parse_id(tmp, len);
1488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1489 SILC_STATUS_ERR_NO_CLIENT_ID);
1493 /* Get Channel ID */
1494 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1496 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1497 SILC_STATUS_ERR_NO_CHANNEL_ID);
1500 channel_id = silc_id_payload_parse_id(tmp, len);
1502 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1503 SILC_STATUS_ERR_NO_CHANNEL_ID);
1507 /* Check whether the channel exists */
1508 channel = silc_idlist_find_channel_by_id(server->local_list,
1511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1512 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1516 /* Check whether the sender of this command is on the channel. */
1517 sender = (SilcClientEntry)sock->user_data;
1518 if (!silc_server_client_on_channel(sender, channel)) {
1519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1520 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1524 /* Check whether the channel is invite-only channel. If yes then the
1525 sender of this command must be at least channel operator. */
1526 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1527 SilcChannelClientEntry chl;
1529 silc_list_start(channel->user_list);
1530 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1531 if (chl->client == sender) {
1532 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1534 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1541 /* Find the connection data for the destination. If it is local we will
1542 send it directly otherwise we will send it to router for routing. */
1543 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1545 dest_sock = (SilcSocketConnection)dest->connection;
1547 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1549 /* Check whether the requested client is already on the channel. */
1550 /* XXX if we are normal server we don't know about global clients on
1551 the channel thus we must request it (USERS command), check from
1552 local cache as well. */
1553 if (silc_server_client_on_channel(dest, channel)) {
1554 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1555 SILC_STATUS_ERR_USER_ON_CHANNEL);
1559 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1561 /* Send notify to the client that is invited to the channel */
1562 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1564 SILC_NOTIFY_TYPE_INVITE, 2,
1565 sidp->data, sidp->len, tmp, len);
1567 /* Send command reply */
1568 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1571 silc_buffer_free(sidp);
1574 silc_server_command_free(cmd);
1579 SilcSocketConnection sock;
1583 /* Quits connection to client. This gets called if client won't
1584 close the connection even when it has issued QUIT command. */
1586 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1588 QuitInternal q = (QuitInternal)context;
1590 /* Free all client specific data, such as client entry and entires
1591 on channels this client may be on. */
1592 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1594 q->sock->user_data = NULL;
1596 /* Close the connection on our side */
1597 silc_server_close_connection(q->server, q->sock);
1599 silc_free(q->signoff);
1603 /* Quits SILC session. This is the normal way to disconnect client. */
1605 SILC_SERVER_CMD_FUNC(quit)
1607 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1608 SilcServer server = cmd->server;
1609 SilcSocketConnection sock = cmd->sock;
1611 unsigned char *tmp = NULL;
1612 unsigned int len = 0;
1614 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
1616 /* Get destination ID */
1617 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1621 q = silc_calloc(1, sizeof(*q));
1624 q->signoff = tmp ? strdup(tmp) : NULL;
1626 /* We quit the connection with little timeout */
1627 silc_task_register(server->timeout_queue, sock->sock,
1628 silc_server_command_quit_cb, (void *)q,
1629 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1631 silc_server_command_free(cmd);
1634 SILC_SERVER_CMD_FUNC(kill)
1638 /* Server side of command INFO. This sends information about us to
1639 the client. If client requested specific server we will send the
1640 command to that server. */
1642 SILC_SERVER_CMD_FUNC(info)
1644 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1645 SilcServer server = cmd->server;
1646 SilcBuffer packet, idp;
1647 char info_string[256], *dest_server;
1649 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1651 /* Get server name */
1652 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1654 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1655 SILC_STATUS_ERR_NO_SUCH_SERVER);
1659 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1660 /* Send our reply */
1661 memset(info_string, 0, sizeof(info_string));
1662 snprintf(info_string, sizeof(info_string),
1663 "location: %s server: %s admin: %s <%s>",
1664 server->config->admin_info->location,
1665 server->config->admin_info->server_type,
1666 server->config->admin_info->admin_name,
1667 server->config->admin_info->admin_email);
1669 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1671 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1672 SILC_STATUS_OK, 0, 2,
1673 2, idp->data, idp->len,
1675 strlen(info_string));
1676 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1677 packet->data, packet->len, FALSE);
1679 silc_buffer_free(packet);
1680 silc_buffer_free(idp);
1682 /* Send this command to the requested server */
1684 if (server->server_type == SILC_SERVER && !server->standalone) {
1688 if (server->server_type == SILC_ROUTER) {
1694 silc_server_command_free(cmd);
1697 /* Server side of command PING. This just replies to the ping. */
1699 SILC_SERVER_CMD_FUNC(ping)
1701 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1702 SilcServer server = cmd->server;
1707 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1710 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1712 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1713 SILC_STATUS_ERR_NO_SERVER_ID);
1716 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1720 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1721 /* Send our reply */
1722 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1725 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1726 SILC_STATUS_ERR_NO_SUCH_SERVER);
1733 silc_server_command_free(cmd);
1736 /* Assembles USERS command and executes it. This is called when client
1737 joins to a channel and we wan't to send USERS command reply to the
1740 void silc_server_command_send_users(SilcServer server,
1741 SilcSocketConnection sock,
1742 SilcChannelEntry channel,
1745 SilcServerCommandContext cmd;
1746 SilcBuffer buffer, idp;
1747 SilcPacketContext *packet = silc_packet_context_alloc();
1749 SILC_LOG_DEBUG(("Start"));
1751 /* Create USERS command packet and process it. */
1752 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1753 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1754 1, idp->data, idp->len);
1756 packet->buffer = silc_buffer_copy(buffer);
1757 packet->sock = sock;
1758 packet->type = SILC_PACKET_COMMAND;
1760 cmd = silc_server_command_alloc();
1761 cmd->payload = silc_command_payload_parse(buffer);
1762 if (!cmd->payload) {
1764 silc_buffer_free(buffer);
1765 silc_buffer_free(idp);
1766 silc_packet_context_free(packet);
1769 cmd->args = silc_command_get_args(cmd->payload);
1770 cmd->server = server;
1771 cmd->sock = silc_socket_dup(sock);
1772 cmd->packet = silc_packet_context_dup(packet);
1773 cmd->pending = FALSE;
1776 /* If this function was called from pending command then instead of
1777 processing the command now, register a pending command callback which
1778 will process it after we've received the automatic USERS command
1779 reply which server will send in JOIN. */
1780 silc_server_command_pending(server, SILC_COMMAND_USERS, 0, NULL,
1781 silc_server_command_users, cmd);
1782 cmd->pending = TRUE;
1783 silc_buffer_free(buffer);
1784 silc_buffer_free(idp);
1788 /* Process USERS command. */
1789 silc_server_command_users((void *)cmd);
1791 silc_buffer_free(buffer);
1792 silc_buffer_free(idp);
1793 silc_packet_context_free(packet);
1796 /* Internal routine to join channel. The channel sent to this function
1797 has been either created or resolved from ID lists. This joins the sent
1798 client to the channel. */
1800 static void silc_server_command_join_channel(SilcServer server,
1801 SilcServerCommandContext cmd,
1802 SilcChannelEntry channel,
1803 SilcClientID *client_id,
1807 SilcSocketConnection sock = cmd->sock;
1809 unsigned int tmp_len;
1810 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1811 SilcClientEntry client;
1812 SilcChannelClientEntry chl;
1813 SilcBuffer reply, chidp, clidp, keyp;
1814 unsigned short ident = silc_command_get_ident(cmd->payload);
1816 SILC_LOG_DEBUG(("Start"));
1821 /* Get passphrase */
1822 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1824 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1825 memcpy(passphrase, tmp, tmp_len);
1829 * Check channel modes
1832 /* Check invite list if channel is invite-only channel */
1833 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1834 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1835 /* Invite list is specified. Check whether client is invited in the
1836 list. If not, then check whether it has been invited otherwise. */
1839 /* XXX client must be invited to be able to join the channel */
1843 /* Check ban list if set */
1844 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1848 /* Check the channel passphrase if set. */
1849 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1850 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1851 strlen(channel->mode_data.passphrase))) {
1852 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1853 SILC_STATUS_ERR_BAD_PASSWORD);
1858 /* Check user count limit if set. */
1859 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1860 if (silc_list_count(channel->user_list) + 1 >
1861 channel->mode_data.user_limit) {
1862 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1863 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1869 * Client is allowed to join to the channel. Make it happen.
1872 /* Get the client entry */
1873 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1874 client = (SilcClientEntry)sock->user_data;
1876 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1879 /* XXX actually this is useless since router finds always cell's
1880 local clients from its local lists. */
1881 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1888 /* Check whether the client already is on the channel */
1889 if (silc_server_client_on_channel(client, channel)) {
1890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1891 SILC_STATUS_ERR_USER_ON_CHANNEL);
1895 /* Generate new channel key as protocol dictates */
1896 if ((!created && silc_list_count(channel->user_list) > 0) ||
1897 !channel->channel_key)
1898 silc_server_create_channel_key(server, channel, 0);
1900 /* Send the channel key. This is broadcasted to the channel but is not
1901 sent to the client who is joining to the channel. */
1902 silc_server_send_channel_key(server, NULL, channel,
1903 server->server_type == SILC_ROUTER ?
1904 FALSE : !server->standalone);
1906 /* Join the client to the channel by adding it to channel's user list.
1907 Add also the channel to client entry's channels list for fast cross-
1909 chl = silc_calloc(1, sizeof(*chl));
1911 chl->client = client;
1912 chl->channel = channel;
1913 silc_list_add(channel->user_list, chl);
1914 silc_list_add(client->channels, chl);
1916 /* Encode Client ID Payload of the original client who wants to join */
1917 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1919 /* Encode command reply packet */
1920 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1921 SILC_PUT32_MSB(channel->mode, mode);
1922 SILC_PUT32_MSB(created, tmp2);
1923 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1924 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1925 strlen(channel->channel_key->
1927 channel->channel_key->cipher->name,
1928 channel->key_len / 8, channel->key);
1930 if (!channel->topic) {
1932 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1933 SILC_STATUS_OK, ident, 5,
1934 2, channel->channel_name,
1935 strlen(channel->channel_name),
1936 3, chidp->data, chidp->len,
1939 6, keyp->data, keyp->len);
1942 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1943 SILC_STATUS_OK, ident, 6,
1944 2, channel->channel_name,
1945 strlen(channel->channel_name),
1946 3, chidp->data, chidp->len,
1949 6, keyp->data, keyp->len,
1951 strlen(channel->topic));
1954 /* Send command reply */
1955 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1956 reply->data, reply->len, FALSE);
1958 if (!cmd->pending) {
1959 /* Send JOIN notify to locally connected clients on the channel */
1960 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1961 SILC_NOTIFY_TYPE_JOIN, 2,
1962 clidp->data, clidp->len,
1963 chidp->data, chidp->len);
1965 /* Send JOIN notify packet to our primary router */
1966 if (!server->standalone)
1967 silc_server_send_notify_join(server, server->router->connection,
1968 server->server_type == SILC_ROUTER ?
1969 TRUE : FALSE, channel, client->id,
1970 SILC_ID_CLIENT_LEN);
1973 /* Send USERS command reply to the joined channel so the user sees who
1974 is currently on the channel. */
1975 silc_server_command_send_users(server, sock, channel, cmd->pending);
1977 silc_buffer_free(reply);
1978 silc_buffer_free(clidp);
1979 silc_buffer_free(chidp);
1980 silc_buffer_free(keyp);
1984 silc_free(passphrase);
1987 /* Server side of command JOIN. Joins client into requested channel. If
1988 the channel does not exist it will be created. */
1990 SILC_SERVER_CMD_FUNC(join)
1992 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1993 SilcServer server = cmd->server;
1995 char *tmp, *channel_name = NULL, *cipher = NULL;
1996 SilcChannelEntry channel;
1997 unsigned int umode = 0;
1998 int created = FALSE;
1999 SilcClientID *client_id;
2001 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2003 /* Get channel name */
2004 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2006 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2007 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2012 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2013 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2014 SILC_STATUS_ERR_BAD_CHANNEL);
2015 silc_free(channel_name);
2019 /* Get Client ID of the client who is joining to the channel */
2020 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2022 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2023 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2026 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2029 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2033 /* Get cipher name */
2034 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2036 /* See if the channel exists */
2037 channel = silc_idlist_find_channel_by_name(server->local_list,
2038 channel_name, NULL);
2040 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2041 /* If this is coming from client the Client ID in the command packet must
2042 be same as the client's ID. */
2043 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2044 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2045 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2046 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2047 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2053 /* Channel not found */
2055 /* If we are standalone server we don't have a router, we just create
2056 the channel by ourselves. */
2057 if (server->standalone) {
2058 channel = silc_server_create_new_channel(server, server->id, cipher,
2059 channel_name, TRUE);
2060 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2065 /* The channel does not exist on our server. If we are normal server
2066 we will send JOIN command to our router which will handle the
2067 joining procedure (either creates the channel if it doesn't exist
2068 or joins the client to it). */
2069 if (server->server_type == SILC_SERVER) {
2071 unsigned short old_ident;
2073 old_ident = silc_command_get_ident(cmd->payload);
2074 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2075 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2077 /* Send JOIN command to our router */
2078 silc_server_packet_send(server, (SilcSocketConnection)
2079 server->router->connection,
2080 SILC_PACKET_COMMAND, cmd->packet->flags,
2081 tmpbuf->data, tmpbuf->len, TRUE);
2083 /* Reprocess this packet after received reply from router */
2084 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2085 silc_command_get_ident(cmd->payload),
2086 silc_server_command_destructor,
2087 silc_server_command_join,
2088 silc_server_command_dup(cmd));
2089 cmd->pending = TRUE;
2093 /* We are router and the channel does not seem exist so we will check
2094 our global list as well for the channel. */
2095 channel = silc_idlist_find_channel_by_name(server->global_list,
2096 channel_name, NULL);
2098 /* Channel really does not exist, create it */
2099 channel = silc_server_create_new_channel(server, server->id, cipher,
2100 channel_name, TRUE);
2101 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2108 /* Channel not found */
2110 /* If the command came from router and/or we are normal server then
2111 something went wrong with the joining as the channel was not found.
2112 We can't do anything else but ignore this. */
2113 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2114 server->server_type == SILC_SERVER)
2117 /* We are router and the channel does not seem exist so we will check
2118 our global list as well for the channel. */
2119 channel = silc_idlist_find_channel_by_name(server->global_list,
2120 channel_name, NULL);
2122 /* Channel really does not exist, create it */
2123 channel = silc_server_create_new_channel(server, server->id, cipher,
2124 channel_name, TRUE);
2125 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2131 /* If the channel does not have global users and is also empty it means the
2132 channel was created globally (by our router) and the client will be the
2133 channel founder and operator. */
2134 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2135 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2136 created = TRUE; /* Created globally by our router */
2139 /* Join to the channel */
2140 silc_server_command_join_channel(server, cmd, channel, client_id,
2143 silc_free(client_id);
2146 silc_server_command_free(cmd);
2149 /* Server side of command MOTD. Sends server's current "message of the
2150 day" to the client. */
2152 SILC_SERVER_CMD_FUNC(motd)
2154 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2155 SilcServer server = cmd->server;
2159 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2161 /* XXX show currently only our motd */
2163 if (server->config && server->config->motd &&
2164 server->config->motd->motd_file) {
2167 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2172 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2178 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2183 silc_server_command_free(cmd);
2186 SILC_SERVER_CMD_FUNC(umode)
2190 /* Checks that client has rights to add or remove channel modes. If any
2191 of the checks fails FALSE is returned. */
2193 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2194 SilcChannelClientEntry client,
2197 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2198 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2200 /* Check whether has rights to change anything */
2201 if (!is_op && !is_fo)
2204 /* Check whether has rights to change everything */
2208 /* We know that client is channel operator, check that they are not
2209 changing anything that requires channel founder rights. Rest of the
2210 modes are available automatically for channel operator. */
2212 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2213 if (is_op && !is_fo)
2216 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2217 if (is_op && !is_fo)
2222 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2223 if (is_op && !is_fo)
2226 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2227 if (is_op && !is_fo)
2232 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2233 if (is_op && !is_fo)
2236 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2237 if (is_op && !is_fo)
2245 /* Server side command of CMODE. Changes channel mode */
2247 SILC_SERVER_CMD_FUNC(cmode)
2249 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2250 SilcServer server = cmd->server;
2251 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2252 SilcChannelID *channel_id;
2253 SilcChannelEntry channel;
2254 SilcChannelClientEntry chl;
2255 SilcBuffer packet, cidp;
2256 unsigned char *tmp, *tmp_id, *tmp_mask;
2257 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2259 SILC_LOG_DEBUG(("Start"));
2261 argc = silc_argument_get_arg_num(cmd->args);
2263 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2264 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2269 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2273 /* Get Channel ID */
2274 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2277 SILC_STATUS_ERR_NO_CHANNEL_ID);
2280 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2282 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2283 SILC_STATUS_ERR_NO_CHANNEL_ID);
2287 /* Get the channel mode mask */
2288 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2291 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2294 SILC_GET32_MSB(mode_mask, tmp_mask);
2296 /* Get channel entry */
2297 channel = silc_idlist_find_channel_by_id(server->local_list,
2300 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2301 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2305 /* Check whether this client is on the channel */
2306 if (!silc_server_client_on_channel(client, channel)) {
2307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2308 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2312 /* Get entry to the channel user list */
2313 silc_list_start(channel->user_list);
2314 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2315 if (chl->client == client)
2318 /* Check that client has rights to change any requested channel modes */
2319 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2321 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2326 * Check the modes. Modes that requires nothing special operation are
2330 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2331 /* Channel uses private keys to protect traffic. Client(s) has set the
2332 key locally they want to use, server does not know that key. */
2333 /* Nothing interesting to do here now */
2335 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2336 /* The mode is removed and we need to generate and distribute
2337 new channel key. Clients are not using private channel keys
2338 anymore after this. */
2340 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2343 /* Re-generate channel key */
2344 silc_server_create_channel_key(server, channel, 0);
2346 /* Encode channel key payload to be distributed on the channel */
2348 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2349 strlen(channel->channel_key->
2351 channel->channel_key->cipher->name,
2352 channel->key_len / 8, channel->key);
2354 /* If we are normal server then we will send it to our router. If we
2355 are router we will send it to all local servers that has clients on
2357 if (server->server_type == SILC_SERVER) {
2358 if (!server->standalone)
2359 silc_server_packet_send(server,
2360 cmd->server->router->connection,
2361 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2367 /* Send to locally connected clients on the channel */
2368 silc_server_packet_send_local_channel(server, channel,
2369 SILC_PACKET_CHANNEL_KEY, 0,
2370 packet->data, packet->len, FALSE);
2371 silc_buffer_free(packet);
2375 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2376 /* User limit is set on channel */
2377 unsigned int user_limit;
2379 /* Get user limit */
2380 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2382 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2384 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2388 SILC_GET32_MSB(user_limit, tmp);
2389 channel->mode_data.user_limit = user_limit;
2392 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2393 /* User limit mode is unset. Remove user limit */
2394 channel->mode_data.user_limit = 0;
2397 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2398 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2399 /* Passphrase has been set to channel */
2401 /* Get the passphrase */
2402 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2404 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2405 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2409 /* Save the passphrase */
2410 channel->mode_data.passphrase = strdup(tmp);
2413 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2414 /* Passphrase mode is unset. remove the passphrase */
2415 if (channel->mode_data.passphrase) {
2416 silc_free(channel->mode_data.passphrase);
2417 channel->mode_data.passphrase = NULL;
2422 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2423 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2424 /* Ban list is specified for channel */
2427 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2430 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2434 /* XXX check that channel founder is not banned */
2436 /* Save the ban list */
2437 channel->mode_data.ban_list = strdup(tmp);
2440 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2441 /* Ban mode is unset. Remove the entire ban list */
2442 if (channel->mode_data.ban_list) {
2443 silc_free(channel->mode_data.ban_list);
2444 channel->mode_data.ban_list = NULL;
2449 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2450 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2451 /* Invite list is specified for channel */
2453 /* Get invite list */
2454 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2457 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2461 /* Save the invite linst */
2462 channel->mode_data.invite_list = strdup(tmp);
2465 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2466 /* Invite list mode is unset. Remove the entire invite list */
2467 if (channel->mode_data.invite_list) {
2468 silc_free(channel->mode_data.invite_list);
2469 channel->mode_data.invite_list = NULL;
2474 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2475 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2476 /* Cipher to use protect the traffic */
2477 unsigned int key_len = 256;
2481 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2484 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2488 cp = strchr(tmp, ':');
2494 /* XXX Duplicated code, make own function for this!! */
2496 /* Delete old cipher and allocate the new one */
2497 silc_cipher_free(channel->channel_key);
2498 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
2499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2500 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2508 /* Re-generate channel key */
2509 silc_server_create_channel_key(server, channel, key_len);
2511 /* Encode channel key payload to be distributed on the channel */
2513 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2514 strlen(channel->channel_key->
2516 channel->channel_key->cipher->name,
2517 channel->key_len / 8, channel->key);
2519 /* If we are normal server then we will send it to our router. If we
2520 are router we will send it to all local servers that has clients on
2522 if (server->server_type == SILC_SERVER) {
2523 if (!server->standalone)
2524 silc_server_packet_send(server,
2525 cmd->server->router->connection,
2526 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2532 /* Send to locally connected clients on the channel */
2533 silc_server_packet_send_local_channel(server, channel,
2534 SILC_PACKET_CHANNEL_KEY, 0,
2535 packet->data, packet->len, FALSE);
2536 silc_buffer_free(packet);
2539 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2540 /* Cipher mode is unset. Remove the cipher and revert back to
2543 if (channel->mode_data.cipher) {
2544 silc_free(channel->mode_data.cipher);
2545 channel->mode_data.cipher = NULL;
2546 channel->mode_data.key_len = 0;
2549 /* Generate new cipher and key for the channel */
2551 /* XXX Duplicated code, make own function for this!! */
2553 /* Delete old cipher and allocate default one */
2554 silc_cipher_free(channel->channel_key);
2555 if (!channel->cipher)
2556 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
2558 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
2559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2560 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2565 /* Re-generate channel key */
2566 silc_server_create_channel_key(server, channel, 0);
2568 /* Encode channel key payload to be distributed on the channel */
2570 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2571 strlen(channel->channel_key->
2573 channel->channel_key->cipher->name,
2574 channel->key_len / 8, channel->key);
2576 /* If we are normal server then we will send it to our router. If we
2577 are router we will send it to all local servers that has clients on
2579 if (server->server_type == SILC_SERVER) {
2580 if (!server->standalone)
2581 silc_server_packet_send(server,
2582 cmd->server->router->connection,
2583 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2589 /* Send to locally connected clients on the channel */
2590 silc_server_packet_send_local_channel(server, channel,
2591 SILC_PACKET_CHANNEL_KEY, 0,
2592 packet->data, packet->len, FALSE);
2593 silc_buffer_free(packet);
2597 /* Finally, set the mode */
2598 channel->mode = mode_mask;
2600 /* Send CMODE_CHANGE notify */
2601 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2602 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2603 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2604 cidp->data, cidp->len,
2607 /* Set CMODE notify type to network */
2608 if (!server->standalone)
2609 silc_server_send_notify_cmode(server, server->router->connection,
2610 server->server_type == SILC_ROUTER ?
2611 TRUE : FALSE, channel,
2612 mode_mask, client->id, SILC_ID_CLIENT_LEN);
2614 /* Send command reply to sender */
2615 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2616 SILC_STATUS_OK, 0, 1,
2618 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2619 packet->data, packet->len, FALSE);
2621 silc_buffer_free(packet);
2622 silc_free(channel_id);
2626 silc_server_command_free(cmd);
2629 /* Server side of CUMODE command. Changes client's mode on a channel. */
2631 SILC_SERVER_CMD_FUNC(cumode)
2633 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2634 SilcServer server = cmd->server;
2635 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2636 SilcChannelID *channel_id;
2637 SilcClientID *client_id;
2638 SilcChannelEntry channel;
2639 SilcClientEntry target_client;
2640 SilcChannelClientEntry chl;
2641 SilcBuffer packet, idp;
2642 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2643 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
2646 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2648 /* Get Channel ID */
2649 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2651 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2652 SILC_STATUS_ERR_NO_CHANNEL_ID);
2655 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
2657 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2658 SILC_STATUS_ERR_NO_CHANNEL_ID);
2662 /* Get channel entry */
2663 channel = silc_idlist_find_channel_by_id(server->local_list,
2666 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2667 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2671 /* Check whether sender is on the channel */
2672 if (!silc_server_client_on_channel(client, channel)) {
2673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2674 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2678 /* Check that client has rights to change other's rights */
2679 silc_list_start(channel->user_list);
2680 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2681 if (chl->client == client) {
2682 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2683 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2685 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2689 sender_mask = chl->mode;
2694 /* Get the target client's channel mode mask */
2695 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2697 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2698 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2701 SILC_GET32_MSB(target_mask, tmp_mask);
2703 /* Get target Client ID */
2704 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2707 SILC_STATUS_ERR_NO_CLIENT_ID);
2710 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2712 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2713 SILC_STATUS_ERR_NO_CLIENT_ID);
2717 /* Get target client's entry */
2718 target_client = silc_idlist_find_client_by_id(server->local_list,
2720 if (!target_client) {
2721 target_client = silc_idlist_find_client_by_id(server->global_list,
2725 /* Check whether target client is on the channel */
2726 if (!silc_server_client_on_channel(target_client, channel)) {
2727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2728 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2732 /* Get entry to the channel user list */
2733 silc_list_start(channel->user_list);
2734 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2735 if (chl->client == target_client)
2742 /* If the target client is founder, no one else can change their mode
2744 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2745 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2746 SILC_STATUS_ERR_NOT_YOU);
2750 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2751 /* Cannot promote anyone to channel founder */
2752 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2753 SILC_STATUS_ERR_NOT_YOU);
2756 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2757 if (target_client == client) {
2758 /* Remove channel founder rights from itself */
2759 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2763 SILC_STATUS_ERR_NOT_YOU);
2769 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2770 /* Promote to operator */
2771 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2772 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2776 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2777 /* Demote to normal user */
2778 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2783 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2785 /* Send notify to channel, notify only if mode was actually changed. */
2787 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2788 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2789 idp->data, idp->len,
2793 /* Set CUMODE notify type to network */
2794 if (!server->standalone)
2795 silc_server_send_notify_cumode(server, server->router->connection,
2796 server->server_type == SILC_ROUTER ?
2797 TRUE : FALSE, channel,
2798 target_mask, client->id,
2801 SILC_ID_CLIENT_LEN);
2804 /* Send command reply to sender */
2805 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2806 SILC_STATUS_OK, 0, 2,
2808 3, tmp_id, tmp_len);
2809 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2810 packet->data, packet->len, FALSE);
2812 silc_buffer_free(packet);
2813 silc_free(channel_id);
2814 silc_free(client_id);
2815 silc_buffer_free(idp);
2818 silc_server_command_free(cmd);
2821 /* Server side of KICK command. Kicks client out of channel. */
2823 SILC_SERVER_CMD_FUNC(kick)
2825 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2826 SilcServer server = cmd->server;
2827 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2828 SilcClientEntry target_client;
2829 SilcChannelID *channel_id;
2830 SilcClientID *client_id;
2831 SilcChannelEntry channel;
2832 SilcChannelClientEntry chl;
2834 unsigned int tmp_len;
2835 unsigned char *tmp, *comment;
2837 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
2839 /* Get Channel ID */
2840 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2842 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2843 SILC_STATUS_ERR_NO_CHANNEL_ID);
2846 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2849 SILC_STATUS_ERR_NO_CHANNEL_ID);
2853 /* Get channel entry */
2854 channel = silc_idlist_find_channel_by_id(server->local_list,
2857 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2858 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2862 /* Check whether sender is on the channel */
2863 if (!silc_server_client_on_channel(client, channel)) {
2864 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2865 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2869 /* Check that the kicker is channel operator or channel founder */
2870 silc_list_start(channel->user_list);
2871 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2872 if (chl->client == client) {
2873 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2874 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2875 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2882 /* Get target Client ID */
2883 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2885 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2886 SILC_STATUS_ERR_NO_CLIENT_ID);
2889 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2891 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2892 SILC_STATUS_ERR_NO_CLIENT_ID);
2896 /* Get target client's entry */
2897 target_client = silc_idlist_find_client_by_id(server->local_list,
2899 if (!target_client) {
2900 target_client = silc_idlist_find_client_by_id(server->global_list,
2904 /* Check that the target client is not channel founder. Channel founder
2905 cannot be kicked from the channel. */
2906 silc_list_start(channel->user_list);
2907 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2908 if (chl->client == target_client) {
2909 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2910 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2911 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
2918 /* Check whether target client is on the channel */
2919 if (!silc_server_client_on_channel(target_client, channel)) {
2920 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2921 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2927 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2931 /* Send command reply to sender */
2932 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2935 /* Send KICKED notify to local clients on the channel */
2936 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
2937 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2938 SILC_NOTIFY_TYPE_KICKED,
2940 idp->data, idp->len,
2941 comment, comment ? strlen(comment) : 0);
2942 silc_buffer_free(idp);
2944 /* Remove the client from the channel. If the channel does not exist
2945 after removing the client then the client kicked itself of the channel
2946 and we don't have to send anything after that. */
2947 if (!silc_server_remove_from_one_channel(server, NULL, channel,
2948 target_client, FALSE))
2951 /* Send KICKED notify to primary route */
2952 if (!server->standalone)
2953 silc_server_send_notify_kicked(server, server->router->connection,
2954 server->server_type == SILC_ROUTER ?
2955 TRUE : FALSE, channel,
2956 target_client->id, SILC_ID_CLIENT_LEN,
2959 /* Re-generate channel key */
2960 silc_server_create_channel_key(server, channel, 0);
2962 /* Send the channel key to the channel. The key of course is not sent
2963 to the client who joined the channel. */
2964 silc_server_send_channel_key(server, target_client->connection, channel,
2965 server->server_type == SILC_ROUTER ?
2966 FALSE : !server->standalone);
2969 silc_server_command_free(cmd);
2972 SILC_SERVER_CMD_FUNC(oper)
2976 SILC_SERVER_CMD_FUNC(silcoper)
2980 /* Server side command of CONNECT. Connects us to the specified remote
2981 server or router. */
2983 SILC_SERVER_CMD_FUNC(connect)
2985 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2986 SilcServer server = cmd->server;
2987 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2989 unsigned int tmp_len;
2990 unsigned int port = SILC_PORT;
2992 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
2994 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2997 /* Check whether client has the permissions. */
2998 if (client->mode == SILC_UMODE_NONE) {
2999 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3000 SILC_STATUS_ERR_NO_SERVER_PRIV);
3004 if (server->server_type == SILC_ROUTER &&
3005 client->mode & SILC_UMODE_SERVER_OPERATOR) {
3006 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3007 SILC_STATUS_ERR_NO_ROUTER_PRIV);
3011 /* Get the remote server */
3012 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3014 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3015 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3020 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3022 SILC_GET32_MSB(port, tmp);
3024 /* Create the connection. It is done with timeout and is async. */
3025 silc_server_create_connection(server, tmp, port);
3027 /* Send reply to the sender */
3028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3032 silc_server_command_free(cmd);
3035 SILC_SERVER_CMD_FUNC(restart)
3039 /* Server side command of CLOSE. Closes connection to a specified server. */
3041 SILC_SERVER_CMD_FUNC(close)
3043 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3044 SilcServer server = cmd->server;
3045 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3046 SilcServerEntry server_entry;
3048 unsigned int tmp_len;
3049 unsigned char *name;
3050 unsigned int port = SILC_PORT;
3052 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3054 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3057 /* Check whether client has the permissions. */
3058 if (client->mode == SILC_UMODE_NONE) {
3059 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3060 SILC_STATUS_ERR_NO_SERVER_PRIV);
3064 /* Get the remote server */
3065 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3068 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3073 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3075 SILC_GET32_MSB(port, tmp);
3077 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3079 if (!server_entry) {
3080 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3081 SILC_STATUS_ERR_NO_SERVER_ID);
3085 /* Close the connection to the server */
3086 silc_server_free_sock_user_data(server, server_entry->connection);
3087 silc_server_disconnect_remote(server, server_entry->connection,
3088 "Server closed connection: "
3089 "Closed by operator");
3091 /* Send reply to the sender */
3092 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3096 silc_server_command_free(cmd);
3099 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3100 active connections. */
3102 SILC_SERVER_CMD_FUNC(shutdown)
3104 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3105 SilcServer server = cmd->server;
3106 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3108 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3110 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3113 /* Check whether client has the permission. */
3114 if (client->mode == SILC_UMODE_NONE) {
3115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3116 SILC_STATUS_ERR_NO_SERVER_PRIV);
3120 /* Then, gracefully, or not, bring the server down. */
3121 silc_server_stop(server);
3123 /* Send reply to the sender */
3124 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3128 silc_server_command_free(cmd);
3131 /* Server side command of LEAVE. Removes client from a channel. */
3133 SILC_SERVER_CMD_FUNC(leave)
3135 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3136 SilcServer server = cmd->server;
3137 SilcSocketConnection sock = cmd->sock;
3138 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3140 SilcChannelEntry channel;
3142 unsigned int i, len;
3145 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3147 /* Get Channel ID */
3148 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3150 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3151 SILC_STATUS_ERR_NO_CHANNEL_ID);
3154 id = silc_id_payload_parse_id(tmp, len);
3156 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3157 SILC_STATUS_ERR_NO_CHANNEL_ID);
3161 /* Get channel entry */
3162 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3164 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3165 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3169 /* Check whether this client is on the channel */
3170 if (!silc_server_client_on_channel(id_entry, channel)) {
3171 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3172 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3176 /* Notify routers that they should remove this client from their list
3177 of clients on the channel. Send LEAVE notify type. */
3178 if (!server->standalone)
3179 silc_server_send_notify_leave(server, server->router->connection,
3180 server->server_type == SILC_ROUTER ?
3181 TRUE : FALSE, channel, id_entry->id,
3182 SILC_ID_CLIENT_LEN);
3184 /* Remove client from channel */
3185 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3187 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3190 /* If the channel does not exist anymore we won't send anything */
3194 /* Re-generate channel key */
3195 silc_server_create_channel_key(server, channel, 0);
3197 /* Encode channel key payload to be distributed on the channel */
3199 silc_channel_key_payload_encode(len, tmp,
3200 strlen(channel->channel_key->cipher->name),
3201 channel->channel_key->cipher->name,
3202 channel->key_len / 8, channel->key);
3204 /* If we are normal server then we will send it to our router. If we
3205 are router we will send it to all local servers that has clients on
3207 if (server->server_type == SILC_SERVER) {
3208 if (!server->standalone)
3209 silc_server_packet_send(server,
3210 cmd->server->router->connection,
3211 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3212 packet->len, FALSE);
3217 /* Send to locally connected clients on the channel */
3218 silc_server_packet_send_local_channel(server, channel,
3219 SILC_PACKET_CHANNEL_KEY, 0,
3220 packet->data, packet->len, FALSE);
3222 silc_buffer_free(packet);
3226 silc_server_command_free(cmd);
3229 /* Server side of command USERS. Resolves clients and their USERS currently
3230 joined on the requested channel. The list of Client ID's and their modes
3231 on the channel is sent back. */
3233 SILC_SERVER_CMD_FUNC(users)
3235 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3236 SilcServer server = cmd->server;
3237 SilcChannelEntry channel;
3238 SilcChannelClientEntry chl;
3241 unsigned char *channel_id;
3242 unsigned int channel_id_len;
3243 SilcBuffer client_id_list;
3244 SilcBuffer client_mode_list;
3246 unsigned char lc[4];
3247 unsigned int list_count = 0;
3248 unsigned short ident = silc_command_get_ident(cmd->payload);
3250 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3252 /* Get Channel ID */
3253 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3255 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3256 SILC_STATUS_ERR_NO_CHANNEL_ID);
3259 id = silc_id_payload_parse_id(channel_id, channel_id_len);
3261 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3262 SILC_STATUS_ERR_NO_CHANNEL_ID);
3266 /* If we are server and we don't know about this channel we will send
3267 the command to our router. If we know about the channel then we also
3268 have the list of users already. */
3269 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3271 if (server->server_type == SILC_SERVER && !server->standalone &&
3275 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3276 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3278 /* Send USERS command */
3279 silc_server_packet_send(server, server->router->connection,
3280 SILC_PACKET_COMMAND, cmd->packet->flags,
3281 tmpbuf->data, tmpbuf->len, TRUE);
3283 /* Reprocess this packet after received reply */
3284 silc_server_command_pending(server, SILC_COMMAND_USERS,
3285 silc_command_get_ident(cmd->payload),
3286 silc_server_command_destructor,
3287 silc_server_command_users,
3288 silc_server_command_dup(cmd));
3289 cmd->pending = TRUE;
3290 silc_command_set_ident(cmd->payload, ident);
3292 silc_buffer_free(tmpbuf);
3297 /* We are router and we will check the global list as well. */
3298 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3300 /* Channel really does not exist */
3301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3302 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3307 /* Assemble the lists now */
3309 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
3310 silc_list_count(channel->user_list));
3311 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
3313 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
3314 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
3316 silc_list_start(channel->user_list);
3317 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3319 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
3320 silc_buffer_put(client_id_list, idp->data, idp->len);
3321 silc_buffer_pull(client_id_list, idp->len);
3322 silc_buffer_free(idp);
3324 /* Client's mode on channel */
3325 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
3326 silc_buffer_pull(client_mode_list, 4);
3330 silc_buffer_push(client_id_list,
3331 client_id_list->data - client_id_list->head);
3332 silc_buffer_push(client_mode_list,
3333 client_mode_list->data - client_mode_list->head);
3336 SILC_PUT32_MSB(list_count, lc);
3339 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3340 SILC_STATUS_OK, 0, 4,
3341 2, channel_id, channel_id_len,
3343 4, client_id_list->data,
3344 client_id_list->len,
3345 5, client_mode_list->data,
3346 client_mode_list->len);
3347 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3348 packet->data, packet->len, FALSE);
3350 silc_buffer_free(packet);
3351 silc_buffer_free(client_id_list);
3352 silc_buffer_free(client_mode_list);
3356 silc_server_command_free(cmd);