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 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
45 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
49 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
54 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(connect, CONNECT,
56 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(restart, RESTART,
66 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
67 SILC_SERVER_CMD(close, CLOSE,
68 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
69 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
71 SILC_SERVER_CMD(silcoper, SILCOPER,
72 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
73 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
74 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
79 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
81 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
83 SILC_LOG_DEBUG(("Start")); \
86 silc_server_command_send_status_reply(cmd, command, \
87 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
88 silc_server_command_free(cmd); \
92 silc_server_command_send_status_reply(cmd, command, \
93 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
94 silc_server_command_free(cmd); \
99 /* Returns TRUE if the connection is registered. Unregistered connections
100 usually cannot send commands hence the check. */
102 static int silc_server_is_registered(SilcServer server,
103 SilcSocketConnection sock,
104 SilcServerCommandContext cmd,
107 SilcIDListData idata = (SilcIDListData)sock->user_data;
108 if (idata->registered)
111 silc_server_command_send_status_reply(cmd, command,
112 SILC_STATUS_ERR_NOT_REGISTERED);
113 silc_server_command_free(cmd);
117 /* Internal context to hold data when executed command with timeout. */
120 SilcSocketConnection sock;
121 SilcPacketContext *packet;
122 } *SilcServerCommandTimeout;
124 /* Timeout callback to process commands with timeout for client. Client's
125 commands are always executed with timeout. */
127 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
129 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
130 SilcServerCommandContext ctx;
131 SilcServerCommand *cmd;
132 SilcClientEntry client = (SilcClientEntry)timeout->sock->user_data;
134 /* Update access time */
135 client->last_command = time(NULL);
137 /* Allocate command context. This must be free'd by the
138 command routine receiving it. */
139 ctx = silc_server_command_alloc();
140 ctx->server = timeout->server;
141 ctx->sock = timeout->sock;
142 ctx->packet = timeout->packet;
144 /* Parse the command payload in the packet */
145 ctx->payload = silc_command_payload_parse(ctx->packet->buffer);
147 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
148 silc_buffer_free(ctx->packet->buffer);
149 silc_socket_free(ctx->sock);
150 silc_packet_context_free(ctx->packet);
155 ctx->args = silc_command_get_args(ctx->payload);
157 /* Execute command. If this fails the packet is dropped. */
158 for (cmd = silc_command_list; cmd->cb; cmd++)
159 if (cmd->cmd == silc_command_get(ctx->payload)) {
161 if (!(cmd->flags & SILC_CF_REG)) {
166 if (silc_server_is_registered(ctx->server, ctx->sock, ctx, cmd->cmd)) {
173 SILC_LOG_ERROR(("Unknown command, packet dropped"));
174 silc_server_command_free(ctx);
182 /* Processes received command packet. */
184 void silc_server_command_process(SilcServer server,
185 SilcSocketConnection sock,
186 SilcPacketContext *packet)
188 SilcServerCommandContext ctx;
189 SilcServerCommand *cmd;
191 /* Execute client's commands always with timeout. Normally they are
192 executed with zero (0) timeout but if client is sending command more
193 frequently than once in 2 seconds, then the timeout may be 0 to 2
195 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
196 SilcClientEntry client = (SilcClientEntry)sock->user_data;
197 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
199 timeout->server = server;
200 timeout->sock = silc_socket_dup(sock);
201 timeout->packet = silc_packet_context_dup(packet);
203 if (client->last_command && (time(NULL) - client->last_command) < 2)
204 silc_task_register(server->timeout_queue, sock->sock,
205 silc_server_command_process_timeout,
207 2 - (time(NULL) - client->last_command), 0,
209 SILC_TASK_PRI_NORMAL);
211 silc_task_register(server->timeout_queue, sock->sock,
212 silc_server_command_process_timeout,
216 SILC_TASK_PRI_NORMAL);
220 /* Allocate command context. This must be free'd by the
221 command routine receiving it. */
222 ctx = silc_server_command_alloc();
223 ctx->server = server;
224 ctx->sock = silc_socket_dup(sock);
225 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
227 /* Parse the command payload in the packet */
228 ctx->payload = silc_command_payload_parse(packet->buffer);
230 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
231 silc_buffer_free(packet->buffer);
232 silc_packet_context_free(packet);
233 silc_socket_free(ctx->sock);
237 ctx->args = silc_command_get_args(ctx->payload);
239 /* Execute command. If this fails the packet is dropped. */
240 for (cmd = silc_command_list; cmd->cb; cmd++)
241 if (cmd->cmd == silc_command_get(ctx->payload)) {
243 if (!(cmd->flags & SILC_CF_REG)) {
248 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
255 SILC_LOG_ERROR(("Unknown command, packet dropped"));
256 silc_server_command_free(ctx);
261 /* Allocate Command Context */
263 SilcServerCommandContext silc_server_command_alloc()
265 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
270 /* Free's the command context allocated before executing the command */
272 void silc_server_command_free(SilcServerCommandContext ctx)
275 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
277 if (ctx->users < 1) {
279 silc_command_free_payload(ctx->payload);
281 silc_packet_context_free(ctx->packet);
283 silc_socket_free(ctx->sock); /* Decrease reference counter */
288 /* Duplicate Command Context by adding reference counter. The context won't
289 be free'd untill it hits zero. */
291 SilcServerCommandContext
292 silc_server_command_dup(SilcServerCommandContext ctx)
295 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
300 /* Add new pending command to be executed when reply to a command has been
301 received. The `reply_cmd' is the command that will call the `callback'
302 with `context' when reply has been received. If `ident' is non-zero
303 the `callback' will be executed when received reply with command
304 identifier `ident'. */
306 void silc_server_command_pending(SilcServer server,
307 SilcCommand reply_cmd,
308 unsigned short ident,
309 SilcServerPendingDestructor destructor,
310 SilcCommandCb callback,
313 SilcServerCommandPending *reply;
315 reply = silc_calloc(1, sizeof(*reply));
316 reply->reply_cmd = reply_cmd;
317 reply->ident = ident;
318 reply->context = context;
319 reply->callback = callback;
320 reply->destructor = destructor;
321 silc_dlist_add(server->pending_commands, reply);
324 /* Deletes pending command by reply command type. */
326 void silc_server_command_pending_del(SilcServer server,
327 SilcCommand reply_cmd,
328 unsigned short ident)
330 SilcServerCommandPending *r;
332 silc_dlist_start(server->pending_commands);
333 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
334 if (r->reply_cmd == reply_cmd && r->ident == ident) {
335 silc_dlist_del(server->pending_commands, r);
341 /* Checks for pending commands and marks callbacks to be called from
342 the command reply function. Returns TRUE if there were pending command. */
344 int silc_server_command_pending_check(SilcServer server,
345 SilcServerCommandReplyContext ctx,
347 unsigned short ident)
349 SilcServerCommandPending *r;
351 silc_dlist_start(server->pending_commands);
352 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
353 if (r->reply_cmd == command && r->ident == ident) {
354 ctx->context = r->context;
355 ctx->callback = r->callback;
356 ctx->destructor = r->destructor;
365 /* Destructor function for pending callbacks. This is called when using
366 pending commands to free the context given for the pending command. */
368 static void silc_server_command_destructor(void *context)
370 silc_server_command_free((SilcServerCommandContext)context);
373 /* Sends simple status message as command reply packet */
376 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
378 SilcCommandStatus status)
382 SILC_LOG_DEBUG(("Sending command status %d", status));
384 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
385 silc_server_packet_send(cmd->server, cmd->sock,
386 SILC_PACKET_COMMAND_REPLY, 0,
387 buffer->data, buffer->len, FALSE);
388 silc_buffer_free(buffer);
391 /* Sends command status reply with one extra argument. The argument
392 type must be sent as argument. */
395 silc_server_command_send_status_data(SilcServerCommandContext cmd,
397 SilcCommandStatus status,
398 unsigned int arg_type,
400 unsigned int arg_len)
404 SILC_LOG_DEBUG(("Sending command status %d", status));
406 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
407 arg_type, arg, arg_len);
408 silc_server_packet_send(cmd->server, cmd->sock,
409 SILC_PACKET_COMMAND_REPLY, 0,
410 buffer->data, buffer->len, FALSE);
411 silc_buffer_free(buffer);
414 /******************************************************************************
418 ******************************************************************************/
421 silc_server_command_whois_parse(SilcServerCommandContext cmd,
422 SilcClientID ***client_id,
423 unsigned int *client_id_count,
431 unsigned int argc = silc_argument_get_arg_num(cmd->args);
434 /* If client ID is in the command it must be used instead of nickname */
435 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
437 /* No ID, get the nickname@server string and parse it. */
438 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
440 if (strchr(tmp, '@')) {
441 len = strcspn(tmp, "@");
442 *nickname = silc_calloc(len + 1, sizeof(char));
443 memcpy(*nickname, tmp, len);
444 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
445 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
447 *nickname = strdup(tmp);
450 silc_server_command_send_status_reply(cmd, command,
451 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
455 /* Command includes ID, we must use that. Also check whether the command
456 has more than one ID set - take them all. */
458 *client_id = silc_calloc(1, sizeof(**client_id));
459 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
460 if ((*client_id)[0] == NULL) {
461 silc_free(*client_id);
464 *client_id_count = 1;
466 /* Take all ID's from the command packet */
468 for (k = 1, i = 1; i < argc; i++) {
469 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
471 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
472 (*client_id_count + 1));
473 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
474 if ((*client_id)[k] == NULL) {
475 /* Cleanup all and fail */
476 for (i = 0; i < *client_id_count; i++)
477 silc_free((*client_id)[i]);
478 silc_free(*client_id);
481 (*client_id_count)++;
487 /* Command includes ID, use that */
490 /* Get the max count of reply messages allowed */
491 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
501 silc_server_command_whois_check(SilcServerCommandContext cmd,
502 SilcClientEntry *clients,
503 unsigned int clients_count)
505 SilcServer server = cmd->server;
507 SilcClientEntry entry;
509 for (i = 0; i < clients_count; i++) {
512 if (!entry->nickname || !entry->username) {
514 unsigned short old_ident;
519 old_ident = silc_command_get_ident(cmd->payload);
520 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
521 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
523 /* Send WHOIS command */
524 silc_server_packet_send(server, entry->router->connection,
525 SILC_PACKET_COMMAND, cmd->packet->flags,
526 tmpbuf->data, tmpbuf->len, TRUE);
528 /* Reprocess this packet after received reply */
529 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
530 silc_command_get_ident(cmd->payload),
531 silc_server_command_destructor,
532 silc_server_command_whois,
533 silc_server_command_dup(cmd));
536 silc_command_set_ident(cmd->payload, old_ident);
538 silc_buffer_free(tmpbuf);
547 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
548 SilcClientEntry *clients,
549 unsigned int clients_count)
551 SilcServer server = cmd->server;
553 int i, count = 0, len;
554 SilcBuffer packet, idp;
555 SilcClientEntry entry;
556 SilcCommandStatus status;
557 unsigned short ident = silc_command_get_ident(cmd->payload);
559 status = SILC_STATUS_OK;
560 if (clients_count > 1)
561 status = SILC_STATUS_LIST_START;
563 for (i = 0; i < clients_count; i++) {
566 if (count && i - 1 == count)
569 if (clients_count > 2)
570 status = SILC_STATUS_LIST_ITEM;
572 if (clients_count > 1 && i == clients_count - 1)
573 status = SILC_STATUS_LIST_END;
575 /* Sanity check, however these should never fail. However, as
576 this sanity check has been added here they have failed. */
577 if (!entry->nickname || !entry->username)
580 /* Send WHOIS reply */
581 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
582 tmp = silc_argument_get_first_arg(cmd->args, NULL);
586 char nh[256], uh[256];
587 unsigned char idle[4];
588 SilcSocketConnection hsock;
590 memset(uh, 0, sizeof(uh));
591 memset(nh, 0, sizeof(nh));
593 strncat(nh, entry->nickname, strlen(entry->nickname));
594 if (!strchr(entry->nickname, '@')) {
596 len = entry->router ? strlen(entry->router->server_name) :
597 strlen(server->server_name);
598 strncat(nh, entry->router ? entry->router->server_name :
599 server->server_name, len);
602 strncat(uh, entry->username, strlen(entry->username));
603 if (!strchr(entry->username, '@')) {
605 hsock = (SilcSocketConnection)entry->connection;
606 len = strlen(hsock->hostname);
607 strncat(uh, hsock->hostname, len);
610 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
613 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
615 2, idp->data, idp->len,
619 strlen(entry->userinfo),
623 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
624 0, packet->data, packet->len, FALSE);
626 silc_buffer_free(packet);
627 silc_buffer_free(idp);
632 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
634 SilcServer server = cmd->server;
635 char *nick = NULL, *server_name = NULL;
636 int count = 0, clients_count = 0;
637 SilcClientEntry *clients = NULL, entry;
638 SilcClientID **client_id = NULL;
639 unsigned int client_id_count = 0;
642 /* Protocol dictates that we must always send the received WHOIS request
643 to our router if we are normal server, so let's do it now unless we
644 are standalone. We will not send any replies to the client until we
645 have received reply from the router. */
646 if (server->server_type == SILC_SERVER &&
647 !cmd->pending && !server->standalone) {
649 unsigned short old_ident;
651 old_ident = silc_command_get_ident(cmd->payload);
652 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
653 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
655 /* Send WHOIS command to our router */
656 silc_server_packet_send(server, (SilcSocketConnection)
657 server->router->connection,
658 SILC_PACKET_COMMAND, cmd->packet->flags,
659 tmpbuf->data, tmpbuf->len, TRUE);
661 /* Reprocess this packet after received reply from router */
662 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
663 silc_command_get_ident(cmd->payload),
664 silc_server_command_destructor,
665 silc_server_command_whois,
666 silc_server_command_dup(cmd));
669 silc_command_set_ident(cmd->payload, old_ident);
671 silc_buffer_free(tmpbuf);
676 /* We are ready to process the command request. Let's search for the
677 requested client and send reply to the requesting client. */
679 /* Parse the whois request */
680 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
681 &nick, &server_name, &count,
685 /* Get all clients matching that ID or nickname from local list */
686 if (client_id_count) {
687 /* Check all Client ID's received in the command packet */
688 for (i = 0; i < client_id_count; i++) {
689 entry = silc_idlist_find_client_by_id(server->local_list,
692 clients = silc_realloc(clients, sizeof(*clients) *
693 (clients_count + 1));
694 clients[clients_count++] = entry;
698 clients = silc_idlist_get_clients_by_nickname(server->local_list,
702 clients = silc_idlist_get_clients_by_hash(server->local_list,
703 nick, server->md5hash,
707 /* Check global list as well */
709 if (client_id_count) {
710 /* Check all Client ID's received in the command packet */
711 for (i = 0; i < client_id_count; i++) {
712 entry = silc_idlist_find_client_by_id(server->global_list,
715 clients = silc_realloc(clients, sizeof(*clients) *
716 (clients_count + 1));
717 clients[clients_count++] = entry;
721 clients = silc_idlist_get_clients_by_nickname(server->global_list,
725 clients = silc_idlist_get_clients_by_hash(server->global_list,
726 nick, server->md5hash,
732 /* Such client(s) really does not exist in the SILC network. */
733 if (!client_id_count) {
734 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
735 SILC_STATUS_ERR_NO_SUCH_NICK,
736 3, nick, strlen(nick));
738 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
739 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
740 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
741 2, idp->data, idp->len);
742 silc_buffer_free(idp);
747 /* Router always finds the client entry if it exists in the SILC network.
748 However, it might be incomplete entry and does not include all the
749 mandatory fields that WHOIS command reply requires. Check for these and
750 make query from the server who owns the client if some fields are
752 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
757 /* Send the command reply to the client */
758 silc_server_command_whois_send_reply(cmd, clients, clients_count);
761 if (client_id_count) {
762 for (i = 0; i < client_id_count; i++)
763 silc_free(client_id[i]);
764 silc_free(client_id);
771 silc_free(server_name);
777 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
779 SilcServer server = cmd->server;
780 char *nick = NULL, *server_name = NULL;
781 int count = 0, clients_count = 0;
782 SilcClientEntry *clients = NULL, entry;
783 SilcClientID **client_id = NULL;
784 unsigned int client_id_count = 0;
787 /* Parse the whois request */
788 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
789 &nick, &server_name, &count,
793 /* Process the command request. Let's search for the requested client and
794 send reply to the requesting server. */
796 if (client_id_count) {
797 /* Check all Client ID's received in the command packet */
798 for (i = 0; i < client_id_count; i++) {
799 entry = silc_idlist_find_client_by_id(server->local_list,
802 clients = silc_realloc(clients, sizeof(*clients) *
803 (clients_count + 1));
804 clients[clients_count++] = entry;
808 clients = silc_idlist_get_clients_by_nickname(server->local_list,
812 clients = silc_idlist_get_clients_by_hash(server->local_list,
813 nick, server->md5hash,
817 /* If we are router we will check our global list as well. */
818 if (!clients && server->server_type == SILC_ROUTER) {
819 if (client_id_count) {
820 /* Check all Client ID's received in the command packet */
821 for (i = 0; i < client_id_count; i++) {
822 entry = silc_idlist_find_client_by_id(server->global_list,
825 clients = silc_realloc(clients, sizeof(*clients) *
826 (clients_count + 1));
827 clients[clients_count++] = entry;
831 clients = silc_idlist_get_clients_by_nickname(server->global_list,
835 clients = silc_idlist_get_clients_by_hash(server->global_list,
836 nick, server->md5hash,
842 /* Such a client really does not exist in the SILC network. */
843 if (!client_id_count) {
844 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
845 SILC_STATUS_ERR_NO_SUCH_NICK,
846 3, nick, strlen(nick));
848 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
849 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
850 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
851 2, idp->data, idp->len);
852 silc_buffer_free(idp);
857 /* Router always finds the client entry if it exists in the SILC network.
858 However, it might be incomplete entry and does not include all the
859 mandatory fields that WHOIS command reply requires. Check for these and
860 make query from the server who owns the client if some fields are
862 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
867 /* Send the command reply to the client */
868 silc_server_command_whois_send_reply(cmd, clients, clients_count);
871 if (client_id_count) {
872 for (i = 0; i < client_id_count; i++)
873 silc_free(client_id[i]);
874 silc_free(client_id);
881 silc_free(server_name);
886 /* Server side of command WHOIS. Processes user's query and sends found
887 results as command replies back to the client. */
889 SILC_SERVER_CMD_FUNC(whois)
891 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
894 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
896 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
897 ret = silc_server_command_whois_from_client(cmd);
898 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
899 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
900 ret = silc_server_command_whois_from_server(cmd);
903 silc_server_command_free(cmd);
906 /* Server side of command WHOWAS. */
908 SILC_SERVER_CMD_FUNC(whowas)
911 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
914 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
916 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
917 ret = silc_server_command_whois_from_client(cmd);
918 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
919 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
920 ret = silc_server_command_whois_from_server(cmd);
923 silc_server_command_free(cmd);
927 /******************************************************************************
931 ******************************************************************************/
933 /* Checks that all mandatory fields are present. If not then send WHOIS
934 request to the server who owns the client. We use WHOIS because we want
935 to get as much information as possible at once. */
938 silc_server_command_identify_check(SilcServerCommandContext cmd,
939 SilcClientEntry *clients,
940 unsigned int clients_count)
942 SilcServer server = cmd->server;
944 SilcClientEntry entry;
946 for (i = 0; i < clients_count; i++) {
949 if (!entry->nickname) {
951 unsigned short old_ident;
956 old_ident = silc_command_get_ident(cmd->payload);
957 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
958 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
959 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
961 /* Send WHOIS request. We send WHOIS since we're doing the requesting
962 now anyway so make it a good one. */
963 silc_server_packet_send(server, entry->router->connection,
964 SILC_PACKET_COMMAND, cmd->packet->flags,
965 tmpbuf->data, tmpbuf->len, TRUE);
967 /* Reprocess this packet after received reply */
968 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
969 silc_command_get_ident(cmd->payload),
970 silc_server_command_destructor,
971 silc_server_command_identify,
972 silc_server_command_dup(cmd));
976 /* Put old data back to the Command Payload we just changed */
977 silc_command_set_ident(cmd->payload, old_ident);
978 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
980 silc_buffer_free(tmpbuf);
989 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
990 SilcClientEntry *clients,
991 unsigned int clients_count)
993 SilcServer server = cmd->server;
995 int i, count = 0, len;
996 SilcBuffer packet, idp;
997 SilcClientEntry entry;
998 SilcCommandStatus status;
999 unsigned short ident = silc_command_get_ident(cmd->payload);
1001 status = SILC_STATUS_OK;
1002 if (clients_count > 1)
1003 status = SILC_STATUS_LIST_START;
1005 for (i = 0; i < clients_count; i++) {
1008 if (count && i - 1 == count)
1011 if (clients_count > 2)
1012 status = SILC_STATUS_LIST_ITEM;
1014 if (clients_count > 1 && i == clients_count - 1)
1015 status = SILC_STATUS_LIST_END;
1017 /* Send IDENTIFY reply */
1018 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1019 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1023 char nh[256], uh[256];
1024 SilcSocketConnection hsock;
1026 memset(uh, 0, sizeof(uh));
1027 memset(nh, 0, sizeof(nh));
1029 strncat(nh, entry->nickname, strlen(entry->nickname));
1030 if (!strchr(entry->nickname, '@')) {
1031 strncat(nh, "@", 1);
1032 len = entry->router ? strlen(entry->router->server_name) :
1033 strlen(server->server_name);
1034 strncat(nh, entry->router ? entry->router->server_name :
1035 server->server_name, len);
1038 if (!entry->username) {
1039 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1041 2, idp->data, idp->len,
1044 strncat(uh, entry->username, strlen(entry->username));
1045 if (!strchr(entry->username, '@')) {
1046 strncat(uh, "@", 1);
1047 hsock = (SilcSocketConnection)entry->connection;
1048 len = strlen(hsock->hostname);
1049 strncat(uh, hsock->hostname, len);
1052 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1054 2, idp->data, idp->len,
1059 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1060 0, packet->data, packet->len, FALSE);
1062 silc_buffer_free(packet);
1063 silc_buffer_free(idp);
1069 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1071 SilcServer server = cmd->server;
1072 char *nick = NULL, *server_name = NULL;
1073 int count = 0, clients_count = 0;
1074 SilcClientEntry *clients = NULL, entry;
1075 SilcClientID **client_id = NULL;
1076 unsigned int client_id_count = 0;
1079 /* Protocol dictates that we must always send the received IDENTIFY request
1080 to our router if we are normal server, so let's do it now unless we
1081 are standalone. We will not send any replies to the client until we
1082 have received reply from the router. */
1083 if (server->server_type == SILC_SERVER &&
1084 !cmd->pending && !server->standalone) {
1086 unsigned short old_ident;
1088 old_ident = silc_command_get_ident(cmd->payload);
1089 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1090 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1092 /* Send IDENTIFY command to our router */
1093 silc_server_packet_send(server, (SilcSocketConnection)
1094 server->router->connection,
1095 SILC_PACKET_COMMAND, cmd->packet->flags,
1096 tmpbuf->data, tmpbuf->len, TRUE);
1098 /* Reprocess this packet after received reply from router */
1099 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1100 silc_command_get_ident(cmd->payload),
1101 silc_server_command_destructor,
1102 silc_server_command_identify,
1103 silc_server_command_dup(cmd));
1104 cmd->pending = TRUE;
1106 silc_command_set_ident(cmd->payload, old_ident);
1108 silc_buffer_free(tmpbuf);
1113 /* We are ready to process the command request. Let's search for the
1114 requested client and send reply to the requesting client. */
1116 /* Parse the IDENTIFY request */
1117 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1118 &nick, &server_name, &count,
1119 SILC_COMMAND_IDENTIFY))
1122 /* Get all clients matching that ID or nickname from local list */
1123 if (client_id_count) {
1124 /* Check all Client ID's received in the command packet */
1125 for (i = 0; i < client_id_count; i++) {
1126 entry = silc_idlist_find_client_by_id(server->local_list,
1127 client_id[i], NULL);
1129 clients = silc_realloc(clients, sizeof(*clients) *
1130 (clients_count + 1));
1131 clients[clients_count++] = entry;
1135 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1139 clients = silc_idlist_get_clients_by_hash(server->local_list,
1140 nick, server->md5hash,
1144 /* Check global list as well */
1146 if (client_id_count) {
1147 /* Check all Client ID's received in the command packet */
1148 for (i = 0; i < client_id_count; i++) {
1149 entry = silc_idlist_find_client_by_id(server->global_list,
1150 client_id[i], NULL);
1152 clients = silc_realloc(clients, sizeof(*clients) *
1153 (clients_count + 1));
1154 clients[clients_count++] = entry;
1158 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1162 clients = silc_idlist_get_clients_by_hash(server->global_list,
1163 nick, server->md5hash,
1169 /* Such a client really does not exist in the SILC network. */
1170 if (!client_id_count) {
1171 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1172 SILC_STATUS_ERR_NO_SUCH_NICK,
1173 3, nick, strlen(nick));
1175 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1176 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1177 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1178 2, idp->data, idp->len);
1179 silc_buffer_free(idp);
1184 /* Check that all mandatory fields are present and request those data
1185 from the server who owns the client if necessary. */
1186 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1191 /* Send the command reply to the client */
1192 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1195 if (client_id_count) {
1196 for (i = 0; i < client_id_count; i++)
1197 silc_free(client_id[i]);
1198 silc_free(client_id);
1205 silc_free(server_name);
1211 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1213 SilcServer server = cmd->server;
1214 char *nick = NULL, *server_name = NULL;
1215 int count = 0, clients_count = 0;
1216 SilcClientEntry *clients = NULL, entry;
1217 SilcClientID **client_id = NULL;
1218 unsigned int client_id_count = 0;
1221 /* Parse the IDENTIFY request */
1222 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1223 &nick, &server_name, &count,
1224 SILC_COMMAND_IDENTIFY))
1227 /* Process the command request. Let's search for the requested client and
1228 send reply to the requesting server. */
1230 if (client_id_count) {
1231 /* Check all Client ID's received in the command packet */
1232 for (i = 0; i < client_id_count; i++) {
1233 entry = silc_idlist_find_client_by_id(server->local_list,
1234 client_id[i], NULL);
1236 clients = silc_realloc(clients, sizeof(*clients) *
1237 (clients_count + 1));
1238 clients[clients_count++] = entry;
1242 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1246 clients = silc_idlist_get_clients_by_hash(server->local_list,
1247 nick, server->md5hash,
1251 /* If we are router we will check our global list as well. */
1252 if (!clients && server->server_type == SILC_ROUTER) {
1253 if (client_id_count) {
1254 /* Check all Client ID's received in the command packet */
1255 for (i = 0; i < client_id_count; i++) {
1256 entry = silc_idlist_find_client_by_id(server->global_list,
1257 client_id[i], NULL);
1259 clients = silc_realloc(clients, sizeof(*clients) *
1260 (clients_count + 1));
1261 clients[clients_count++] = entry;
1265 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1269 clients = silc_idlist_get_clients_by_hash(server->global_list,
1270 nick, server->md5hash,
1276 /* Such a client really does not exist in the SILC network. */
1277 if (!client_id_count) {
1278 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1279 SILC_STATUS_ERR_NO_SUCH_NICK,
1280 3, nick, strlen(nick));
1282 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1283 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1284 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1285 2, idp->data, idp->len);
1286 silc_buffer_free(idp);
1291 /* Check that all mandatory fields are present and request those data
1292 from the server who owns the client if necessary. */
1293 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1298 /* Send the command reply */
1299 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1302 if (client_id_count) {
1303 for (i = 0; i < client_id_count; i++)
1304 silc_free(client_id[i]);
1305 silc_free(client_id);
1312 silc_free(server_name);
1317 SILC_SERVER_CMD_FUNC(identify)
1319 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1322 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1324 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1325 ret = silc_server_command_identify_from_client(cmd);
1326 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1327 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1328 ret = silc_server_command_identify_from_server(cmd);
1331 silc_server_command_free(cmd);
1334 /* Checks string for bad characters and returns TRUE if they are found. */
1336 static int silc_server_command_bad_chars(char *nick)
1338 if (strchr(nick, '\\')) return TRUE;
1339 if (strchr(nick, '\"')) return TRUE;
1340 if (strchr(nick, '´')) return TRUE;
1341 if (strchr(nick, '`')) return TRUE;
1342 if (strchr(nick, '\'')) return TRUE;
1343 if (strchr(nick, '*')) return TRUE;
1344 if (strchr(nick, '/')) return TRUE;
1345 if (strchr(nick, '@')) return TRUE;
1350 /* Server side of command NICK. Sets nickname for user. Setting
1351 nickname causes generation of a new client ID for the client. The
1352 new client ID is sent to the client after changing the nickname. */
1354 SILC_SERVER_CMD_FUNC(nick)
1356 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1357 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1358 SilcServer server = cmd->server;
1359 SilcBuffer packet, nidp, oidp;
1360 SilcClientID *new_id;
1363 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1366 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1368 /* Check nickname */
1369 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1370 if (silc_server_command_bad_chars(nick) == TRUE) {
1371 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1372 SILC_STATUS_ERR_BAD_NICKNAME);
1376 if (strlen(nick) > 128)
1379 /* Create new Client ID */
1380 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1381 cmd->server->md5hash, nick,
1384 /* Send notify about nickname change to our router. We send the new
1385 ID and ask to replace it with the old one. If we are router the
1386 packet is broadcasted. Send NICK_CHANGE notify. */
1387 if (!server->standalone)
1388 silc_server_send_notify_nick_change(server, server->router->connection,
1389 server->server_type == SILC_SERVER ?
1390 FALSE : TRUE, client->id,
1391 new_id, SILC_ID_CLIENT_LEN);
1393 /* Remove old cache entry */
1394 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1397 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1401 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1402 silc_free(client->id);
1405 /* Save the nickname as this client is our local client */
1406 if (client->nickname)
1407 silc_free(client->nickname);
1409 client->nickname = strdup(nick);
1410 client->id = new_id;
1412 /* Update client cache */
1413 silc_idcache_add(server->local_list->clients, client->nickname,
1414 SILC_ID_CLIENT, client->id, (void *)client, TRUE, FALSE);
1416 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1418 /* Send NICK_CHANGE notify to the client's channels */
1419 silc_server_send_notify_on_channels(server, client,
1420 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1421 oidp->data, oidp->len,
1422 nidp->data, nidp->len);
1424 /* Send the new Client ID as reply command back to client */
1425 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1426 SILC_STATUS_OK, 0, 1,
1427 2, nidp->data, nidp->len);
1428 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1429 0, packet->data, packet->len, FALSE);
1431 silc_buffer_free(packet);
1432 silc_buffer_free(nidp);
1433 silc_buffer_free(oidp);
1436 silc_server_command_free(cmd);
1439 SILC_SERVER_CMD_FUNC(list)
1443 /* Server side of TOPIC command. Sets topic for channel and/or returns
1444 current topic to client. */
1446 SILC_SERVER_CMD_FUNC(topic)
1448 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1449 SilcServer server = cmd->server;
1450 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1451 SilcChannelID *channel_id;
1452 SilcChannelEntry channel;
1453 SilcChannelClientEntry chl;
1454 SilcBuffer packet, idp;
1456 unsigned int argc, tmp_len;
1458 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1460 argc = silc_argument_get_arg_num(cmd->args);
1462 /* Get Channel ID */
1463 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1466 SILC_STATUS_ERR_NO_CHANNEL_ID);
1469 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1471 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1472 SILC_STATUS_ERR_NO_CHANNEL_ID);
1476 /* Check whether the channel exists */
1477 channel = silc_idlist_find_channel_by_id(server->local_list,
1480 channel = silc_idlist_find_channel_by_id(server->global_list,
1483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1484 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1491 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1493 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1494 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1498 if (strlen(tmp) > 256) {
1499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1500 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1504 /* See whether has rights to change topic */
1505 silc_list_start(channel->user_list);
1506 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1507 if (chl->client == client)
1510 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1511 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1513 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1518 /* Set the topic for channel */
1520 silc_free(channel->topic);
1521 channel->topic = strdup(tmp);
1523 /* Send TOPIC_SET notify type to the network */
1524 if (!server->standalone)
1525 silc_server_send_notify_topic_set(server, server->router->connection,
1526 server->server_type == SILC_ROUTER ?
1527 TRUE : FALSE, channel, client->id,
1528 SILC_ID_CLIENT_LEN, channel->topic);
1530 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1532 /* Send notify about topic change to all clients on the channel */
1533 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1534 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1535 idp->data, idp->len,
1536 channel->topic, strlen(channel->topic));
1537 silc_buffer_free(idp);
1540 /* Send the topic to client as reply packet */
1541 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1543 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1544 SILC_STATUS_OK, 0, 2,
1545 2, idp->data, idp->len,
1547 strlen(channel->topic));
1549 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1550 SILC_STATUS_OK, 0, 1,
1551 2, idp->data, idp->len);
1552 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1553 0, packet->data, packet->len, FALSE);
1555 silc_buffer_free(packet);
1556 silc_buffer_free(idp);
1557 silc_free(channel_id);
1560 silc_server_command_free(cmd);
1563 /* Server side of INVITE command. Invites some client to join some channel. */
1565 SILC_SERVER_CMD_FUNC(invite)
1567 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1568 SilcServer server = cmd->server;
1569 SilcSocketConnection sock = cmd->sock, dest_sock;
1570 SilcClientEntry sender, dest;
1571 SilcClientID *dest_id;
1572 SilcChannelEntry channel;
1573 SilcChannelID *channel_id;
1578 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1580 /* Get destination ID */
1581 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1583 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1584 SILC_STATUS_ERR_NO_CLIENT_ID);
1587 dest_id = silc_id_payload_parse_id(tmp, len);
1589 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1590 SILC_STATUS_ERR_NO_CLIENT_ID);
1594 /* Get Channel ID */
1595 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1597 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1598 SILC_STATUS_ERR_NO_CHANNEL_ID);
1601 channel_id = silc_id_payload_parse_id(tmp, len);
1603 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1604 SILC_STATUS_ERR_NO_CHANNEL_ID);
1608 /* Check whether the channel exists */
1609 channel = silc_idlist_find_channel_by_id(server->local_list,
1612 channel = silc_idlist_find_channel_by_id(server->global_list,
1615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1616 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1621 /* Check whether the sender of this command is on the channel. */
1622 sender = (SilcClientEntry)sock->user_data;
1623 if (!silc_server_client_on_channel(sender, channel)) {
1624 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1625 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1629 /* Check whether the channel is invite-only channel. If yes then the
1630 sender of this command must be at least channel operator. */
1631 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1632 SilcChannelClientEntry chl;
1634 silc_list_start(channel->user_list);
1635 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1636 if (chl->client == sender) {
1637 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1638 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1639 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1646 /* Find the connection data for the destination. If it is local we will
1647 send it directly otherwise we will send it to router for routing. */
1648 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1650 dest_sock = (SilcSocketConnection)dest->connection;
1652 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1654 /* Check whether the requested client is already on the channel. */
1655 /* XXX if we are normal server we don't know about global clients on
1656 the channel thus we must request it (USERS command), check from
1657 local cache as well. */
1658 if (silc_server_client_on_channel(dest, channel)) {
1659 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1660 SILC_STATUS_ERR_USER_ON_CHANNEL);
1664 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1666 /* Send notify to the client that is invited to the channel */
1667 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1669 SILC_NOTIFY_TYPE_INVITE, 2,
1670 sidp->data, sidp->len, tmp, len);
1672 /* Send command reply */
1673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1676 silc_buffer_free(sidp);
1679 silc_server_command_free(cmd);
1684 SilcSocketConnection sock;
1688 /* Quits connection to client. This gets called if client won't
1689 close the connection even when it has issued QUIT command. */
1691 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1693 QuitInternal q = (QuitInternal)context;
1695 /* Free all client specific data, such as client entry and entires
1696 on channels this client may be on. */
1697 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1699 q->sock->user_data = NULL;
1701 /* Close the connection on our side */
1702 silc_server_close_connection(q->server, q->sock);
1704 silc_free(q->signoff);
1708 /* Quits SILC session. This is the normal way to disconnect client. */
1710 SILC_SERVER_CMD_FUNC(quit)
1712 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1713 SilcServer server = cmd->server;
1714 SilcSocketConnection sock = cmd->sock;
1716 unsigned char *tmp = NULL;
1717 unsigned int len = 0;
1719 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
1721 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1724 /* Get destination ID */
1725 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1729 q = silc_calloc(1, sizeof(*q));
1732 q->signoff = tmp ? strdup(tmp) : NULL;
1734 /* We quit the connection with little timeout */
1735 silc_task_register(server->timeout_queue, sock->sock,
1736 silc_server_command_quit_cb, (void *)q,
1737 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1740 silc_server_command_free(cmd);
1743 SILC_SERVER_CMD_FUNC(kill)
1747 /* Server side of command INFO. This sends information about us to
1748 the client. If client requested specific server we will send the
1749 command to that server. */
1751 SILC_SERVER_CMD_FUNC(info)
1753 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1754 SilcServer server = cmd->server;
1755 SilcBuffer packet, idp;
1756 char info_string[256], *dest_server;
1758 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1760 /* Get server name */
1761 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1764 SILC_STATUS_ERR_NO_SUCH_SERVER);
1768 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1769 /* Send our reply */
1770 memset(info_string, 0, sizeof(info_string));
1771 snprintf(info_string, sizeof(info_string),
1772 "location: %s server: %s admin: %s <%s>",
1773 server->config->admin_info->location,
1774 server->config->admin_info->server_type,
1775 server->config->admin_info->admin_name,
1776 server->config->admin_info->admin_email);
1778 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1780 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1781 SILC_STATUS_OK, 0, 2,
1782 2, idp->data, idp->len,
1784 strlen(info_string));
1785 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1786 packet->data, packet->len, FALSE);
1788 silc_buffer_free(packet);
1789 silc_buffer_free(idp);
1791 /* Send this command to the requested server */
1793 if (server->server_type == SILC_SERVER && !server->standalone) {
1797 if (server->server_type == SILC_ROUTER) {
1803 silc_server_command_free(cmd);
1806 /* Server side of command PING. This just replies to the ping. */
1808 SILC_SERVER_CMD_FUNC(ping)
1810 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1811 SilcServer server = cmd->server;
1816 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1819 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1822 SILC_STATUS_ERR_NO_SERVER_ID);
1825 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1829 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1830 /* Send our reply */
1831 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1835 SILC_STATUS_ERR_NO_SUCH_SERVER);
1842 silc_server_command_free(cmd);
1845 /* Internal routine to join channel. The channel sent to this function
1846 has been either created or resolved from ID lists. This joins the sent
1847 client to the channel. */
1849 static void silc_server_command_join_channel(SilcServer server,
1850 SilcServerCommandContext cmd,
1851 SilcChannelEntry channel,
1852 SilcClientID *client_id,
1856 SilcSocketConnection sock = cmd->sock;
1858 unsigned int tmp_len, user_count;
1859 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
1860 SilcClientEntry client;
1861 SilcChannelClientEntry chl;
1862 SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
1863 unsigned short ident = silc_command_get_ident(cmd->payload);
1865 SILC_LOG_DEBUG(("Start"));
1870 /* Get passphrase */
1871 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1873 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1874 memcpy(passphrase, tmp, tmp_len);
1878 * Check channel modes
1881 /* Check invite list if channel is invite-only channel */
1882 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1883 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1884 /* Invite list is specified. Check whether client is invited in the
1885 list. If not, then check whether it has been invited otherwise. */
1888 /* XXX client must be invited to be able to join the channel */
1892 /* Check ban list if set */
1893 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1897 /* Check the channel passphrase if set. */
1898 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1899 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1900 strlen(channel->mode_data.passphrase))) {
1901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1902 SILC_STATUS_ERR_BAD_PASSWORD);
1907 /* Check user count limit if set. */
1908 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1909 if (silc_list_count(channel->user_list) + 1 >
1910 channel->mode_data.user_limit) {
1911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1912 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1918 * Client is allowed to join to the channel. Make it happen.
1921 /* Get the client entry */
1922 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1923 client = (SilcClientEntry)sock->user_data;
1925 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1928 /* XXX actually this is useless since router finds always cell's
1929 local clients from its local lists. */
1930 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1937 /* Check whether the client already is on the channel */
1938 if (silc_server_client_on_channel(client, channel)) {
1939 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1940 SILC_STATUS_ERR_USER_ON_CHANNEL);
1944 /* Generate new channel key as protocol dictates */
1945 if ((!created && silc_list_count(channel->user_list) > 0) ||
1946 !channel->channel_key)
1947 silc_server_create_channel_key(server, channel, 0);
1949 /* Send the channel key. This is broadcasted to the channel but is not
1950 sent to the client who is joining to the channel. */
1951 silc_server_send_channel_key(server, NULL, channel,
1952 server->server_type == SILC_ROUTER ?
1953 FALSE : !server->standalone);
1955 /* Join the client to the channel by adding it to channel's user list.
1956 Add also the channel to client entry's channels list for fast cross-
1958 chl = silc_calloc(1, sizeof(*chl));
1960 chl->client = client;
1961 chl->channel = channel;
1962 silc_list_add(channel->user_list, chl);
1963 silc_list_add(client->channels, chl);
1965 /* Get users on the channel */
1966 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
1969 /* Encode Client ID Payload of the original client who wants to join */
1970 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1972 /* Encode command reply packet */
1973 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1974 SILC_PUT32_MSB(channel->mode, mode);
1975 SILC_PUT32_MSB(created, tmp2);
1976 SILC_PUT32_MSB(user_count, tmp3);
1977 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1978 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1979 strlen(channel->channel_key->
1981 channel->channel_key->cipher->name,
1982 channel->key_len / 8, channel->key);
1984 if (!channel->topic) {
1986 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1987 SILC_STATUS_OK, ident, 9,
1988 2, channel->channel_name,
1989 strlen(channel->channel_name),
1990 3, chidp->data, chidp->len,
1991 4, clidp->data, clidp->len,
1994 7, keyp->data, keyp->len,
1996 13, user_list->data, user_list->len,
1997 14, mode_list->data,
2001 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2002 SILC_STATUS_OK, ident, 10,
2003 2, channel->channel_name,
2004 strlen(channel->channel_name),
2005 3, chidp->data, chidp->len,
2006 4, clidp->data, clidp->len,
2009 7, keyp->data, keyp->len,
2011 strlen(channel->topic),
2013 13, user_list->data, user_list->len,
2014 14, mode_list->data,
2018 /* Send command reply */
2019 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2020 reply->data, reply->len, FALSE);
2022 if (!cmd->pending) {
2023 /* Send JOIN notify to locally connected clients on the channel */
2024 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2025 SILC_NOTIFY_TYPE_JOIN, 2,
2026 clidp->data, clidp->len,
2027 chidp->data, chidp->len);
2029 /* Send JOIN notify packet to our primary router */
2030 if (!server->standalone)
2031 silc_server_send_notify_join(server, server->router->connection,
2032 server->server_type == SILC_ROUTER ?
2033 TRUE : FALSE, channel, client->id,
2034 SILC_ID_CLIENT_LEN);
2037 silc_buffer_free(reply);
2038 silc_buffer_free(clidp);
2039 silc_buffer_free(chidp);
2040 silc_buffer_free(keyp);
2041 silc_buffer_free(user_list);
2042 silc_buffer_free(mode_list);
2046 silc_free(passphrase);
2049 /* Server side of command JOIN. Joins client into requested channel. If
2050 the channel does not exist it will be created. */
2052 SILC_SERVER_CMD_FUNC(join)
2054 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2055 SilcServer server = cmd->server;
2057 char *tmp, *channel_name = NULL, *cipher, *hmac;
2058 SilcChannelEntry channel;
2059 unsigned int umode = 0;
2060 int created = FALSE;
2061 SilcClientID *client_id;
2063 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2065 /* Get channel name */
2066 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2068 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2069 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2074 if (strlen(channel_name) > 256)
2075 channel_name[255] = '\0';
2077 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2079 SILC_STATUS_ERR_BAD_CHANNEL);
2080 silc_free(channel_name);
2084 /* Get Client ID of the client who is joining to the channel */
2085 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2087 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2088 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2091 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2094 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2098 /* Get cipher and hmac name */
2099 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2100 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2102 /* See if the channel exists */
2103 channel = silc_idlist_find_channel_by_name(server->local_list,
2104 channel_name, NULL);
2106 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2107 /* If this is coming from client the Client ID in the command packet must
2108 be same as the client's ID. */
2109 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2110 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2111 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2112 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2113 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2119 /* Channel not found */
2121 /* If we are standalone server we don't have a router, we just create
2122 the channel by ourselves. */
2123 if (server->standalone) {
2124 channel = silc_server_create_new_channel(server, server->id, cipher,
2125 hmac, channel_name, TRUE);
2126 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2131 /* The channel does not exist on our server. If we are normal server
2132 we will send JOIN command to our router which will handle the
2133 joining procedure (either creates the channel if it doesn't exist
2134 or joins the client to it). */
2135 if (server->server_type == SILC_SERVER) {
2137 unsigned short old_ident;
2139 old_ident = silc_command_get_ident(cmd->payload);
2140 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2141 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2143 /* Send JOIN command to our router */
2144 silc_server_packet_send(server, (SilcSocketConnection)
2145 server->router->connection,
2146 SILC_PACKET_COMMAND, cmd->packet->flags,
2147 tmpbuf->data, tmpbuf->len, TRUE);
2149 /* Reprocess this packet after received reply from router */
2150 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2151 silc_command_get_ident(cmd->payload),
2152 silc_server_command_destructor,
2153 silc_server_command_join,
2154 silc_server_command_dup(cmd));
2155 cmd->pending = TRUE;
2159 /* We are router and the channel does not seem exist so we will check
2160 our global list as well for the channel. */
2161 channel = silc_idlist_find_channel_by_name(server->global_list,
2162 channel_name, NULL);
2164 /* Channel really does not exist, create it */
2165 channel = silc_server_create_new_channel(server, server->id, cipher,
2166 hmac, channel_name, TRUE);
2167 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2174 /* Channel not found */
2176 /* If the command came from router and/or we are normal server then
2177 something went wrong with the joining as the channel was not found.
2178 We can't do anything else but ignore this. */
2179 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2180 server->server_type == SILC_SERVER)
2183 /* We are router and the channel does not seem exist so we will check
2184 our global list as well for the channel. */
2185 channel = silc_idlist_find_channel_by_name(server->global_list,
2186 channel_name, NULL);
2188 /* Channel really does not exist, create it */
2189 channel = silc_server_create_new_channel(server, server->id, cipher,
2190 hmac, channel_name, TRUE);
2191 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2197 /* If the channel does not have global users and is also empty it means the
2198 channel was created globally (by our router) and the client will be the
2199 channel founder and operator. */
2200 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2201 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2202 created = TRUE; /* Created globally by our router */
2205 /* Join to the channel */
2206 silc_server_command_join_channel(server, cmd, channel, client_id,
2209 silc_free(client_id);
2212 silc_server_command_free(cmd);
2215 /* Server side of command MOTD. Sends server's current "message of the
2216 day" to the client. */
2218 SILC_SERVER_CMD_FUNC(motd)
2220 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2221 SilcServer server = cmd->server;
2225 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2227 /* XXX show currently only our motd */
2229 if (server->config && server->config->motd &&
2230 server->config->motd->motd_file) {
2233 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2238 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2249 silc_server_command_free(cmd);
2252 SILC_SERVER_CMD_FUNC(umode)
2256 /* Checks that client has rights to add or remove channel modes. If any
2257 of the checks fails FALSE is returned. */
2259 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2260 SilcChannelClientEntry client,
2263 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2264 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2266 /* Check whether has rights to change anything */
2267 if (!is_op && !is_fo)
2270 /* Check whether has rights to change everything */
2274 /* We know that client is channel operator, check that they are not
2275 changing anything that requires channel founder rights. Rest of the
2276 modes are available automatically for channel operator. */
2278 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2279 if (is_op && !is_fo)
2282 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2283 if (is_op && !is_fo)
2288 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2289 if (is_op && !is_fo)
2292 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2293 if (is_op && !is_fo)
2298 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2299 if (is_op && !is_fo)
2302 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2303 if (is_op && !is_fo)
2311 /* Server side command of CMODE. Changes channel mode */
2313 SILC_SERVER_CMD_FUNC(cmode)
2315 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2316 SilcServer server = cmd->server;
2317 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2318 SilcChannelID *channel_id;
2319 SilcChannelEntry channel;
2320 SilcChannelClientEntry chl;
2321 SilcBuffer packet, cidp;
2322 unsigned char *tmp, *tmp_id, *tmp_mask;
2323 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2325 SILC_LOG_DEBUG(("Start"));
2327 argc = silc_argument_get_arg_num(cmd->args);
2329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2330 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2335 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2339 /* Get Channel ID */
2340 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2343 SILC_STATUS_ERR_NO_CHANNEL_ID);
2346 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2348 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2349 SILC_STATUS_ERR_NO_CHANNEL_ID);
2353 /* Get the channel mode mask */
2354 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2357 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2360 SILC_GET32_MSB(mode_mask, tmp_mask);
2362 /* Get channel entry */
2363 channel = silc_idlist_find_channel_by_id(server->local_list,
2366 channel = silc_idlist_find_channel_by_id(server->global_list,
2369 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2370 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2375 /* Check whether this client is on the channel */
2376 if (!silc_server_client_on_channel(client, channel)) {
2377 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2378 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2382 /* Get entry to the channel user list */
2383 silc_list_start(channel->user_list);
2384 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2385 if (chl->client == client)
2388 /* Check that client has rights to change any requested channel modes */
2389 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2391 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2396 * Check the modes. Modes that requires nothing special operation are
2400 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2401 /* Channel uses private keys to protect traffic. Client(s) has set the
2402 key locally they want to use, server does not know that key. */
2403 /* Nothing interesting to do here now */
2405 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2406 /* The mode is removed and we need to generate and distribute
2407 new channel key. Clients are not using private channel keys
2408 anymore after this. */
2410 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2413 /* Re-generate channel key */
2414 silc_server_create_channel_key(server, channel, 0);
2416 /* Encode channel key payload to be distributed on the channel */
2418 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2419 strlen(channel->channel_key->
2421 channel->channel_key->cipher->name,
2422 channel->key_len / 8, channel->key);
2424 /* If we are normal server then we will send it to our router. If we
2425 are router we will send it to all local servers that has clients on
2427 if (server->server_type == SILC_SERVER) {
2428 if (!server->standalone)
2429 silc_server_packet_send(server,
2430 cmd->server->router->connection,
2431 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2437 /* Send to locally connected clients on the channel */
2438 silc_server_packet_send_local_channel(server, channel,
2439 SILC_PACKET_CHANNEL_KEY, 0,
2440 packet->data, packet->len, FALSE);
2441 silc_buffer_free(packet);
2445 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2446 /* User limit is set on channel */
2447 unsigned int user_limit;
2449 /* Get user limit */
2450 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2452 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2454 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2458 SILC_GET32_MSB(user_limit, tmp);
2459 channel->mode_data.user_limit = user_limit;
2462 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2463 /* User limit mode is unset. Remove user limit */
2464 channel->mode_data.user_limit = 0;
2467 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2468 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2469 /* Passphrase has been set to channel */
2471 /* Get the passphrase */
2472 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2474 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2475 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2479 /* Save the passphrase */
2480 channel->mode_data.passphrase = strdup(tmp);
2483 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2484 /* Passphrase mode is unset. remove the passphrase */
2485 if (channel->mode_data.passphrase) {
2486 silc_free(channel->mode_data.passphrase);
2487 channel->mode_data.passphrase = NULL;
2492 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2493 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2494 /* Ban list is specified for channel */
2497 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2500 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2504 /* XXX check that channel founder is not banned */
2506 /* Save the ban list */
2507 channel->mode_data.ban_list = strdup(tmp);
2510 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2511 /* Ban mode is unset. Remove the entire ban list */
2512 if (channel->mode_data.ban_list) {
2513 silc_free(channel->mode_data.ban_list);
2514 channel->mode_data.ban_list = NULL;
2519 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2520 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2521 /* Invite list is specified for channel */
2523 /* Get invite list */
2524 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2527 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2531 /* Save the invite linst */
2532 channel->mode_data.invite_list = strdup(tmp);
2535 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2536 /* Invite list mode is unset. Remove the entire invite list */
2537 if (channel->mode_data.invite_list) {
2538 silc_free(channel->mode_data.invite_list);
2539 channel->mode_data.invite_list = NULL;
2544 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2545 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2546 /* Cipher to use protect the traffic */
2547 unsigned int key_len;
2550 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2552 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2553 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2557 /* XXX Duplicated code, make own function for this!! */
2559 /* Delete old cipher and allocate the new one */
2560 silc_cipher_free(channel->channel_key);
2561 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
2562 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2563 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2566 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
2568 /* Re-generate channel key */
2569 silc_server_create_channel_key(server, channel, key_len);
2571 /* Encode channel key payload to be distributed on the channel */
2573 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2574 strlen(channel->channel_key->
2576 channel->channel_key->cipher->name,
2577 channel->key_len / 8, channel->key);
2579 /* If we are normal server then we will send it to our router. If we
2580 are router we will send it to all local servers that has clients on
2582 if (server->server_type == SILC_SERVER) {
2583 if (!server->standalone)
2584 silc_server_packet_send(server,
2585 cmd->server->router->connection,
2586 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2592 /* Send to locally connected clients on the channel */
2593 silc_server_packet_send_local_channel(server, channel,
2594 SILC_PACKET_CHANNEL_KEY, 0,
2595 packet->data, packet->len, FALSE);
2596 silc_buffer_free(packet);
2599 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2600 /* Cipher mode is unset. Remove the cipher and revert back to
2603 if (channel->mode_data.cipher) {
2604 silc_free(channel->mode_data.cipher);
2605 channel->mode_data.cipher = NULL;
2606 channel->mode_data.key_len = 0;
2609 /* Generate new cipher and key for the channel */
2611 /* XXX Duplicated code, make own function for this!! */
2613 /* Delete old cipher and allocate default one */
2614 silc_cipher_free(channel->channel_key);
2615 if (!channel->cipher)
2616 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
2618 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
2619 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2620 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2625 /* Re-generate channel key */
2626 silc_server_create_channel_key(server, channel, 0);
2628 /* Encode channel key payload to be distributed on the channel */
2630 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2631 strlen(channel->channel_key->
2633 channel->channel_key->cipher->name,
2634 channel->key_len / 8, channel->key);
2636 /* If we are normal server then we will send it to our router. If we
2637 are router we will send it to all local servers that has clients on
2639 if (server->server_type == SILC_SERVER) {
2640 if (!server->standalone)
2641 silc_server_packet_send(server,
2642 cmd->server->router->connection,
2643 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2649 /* Send to locally connected clients on the channel */
2650 silc_server_packet_send_local_channel(server, channel,
2651 SILC_PACKET_CHANNEL_KEY, 0,
2652 packet->data, packet->len, FALSE);
2653 silc_buffer_free(packet);
2657 /* Finally, set the mode */
2658 channel->mode = mode_mask;
2660 /* Send CMODE_CHANGE notify */
2661 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2662 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2663 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2664 cidp->data, cidp->len,
2667 /* Set CMODE notify type to network */
2668 if (!server->standalone)
2669 silc_server_send_notify_cmode(server, server->router->connection,
2670 server->server_type == SILC_ROUTER ?
2671 TRUE : FALSE, channel,
2672 mode_mask, client->id, SILC_ID_CLIENT_LEN);
2674 /* Send command reply to sender */
2675 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2676 SILC_STATUS_OK, 0, 1,
2678 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2679 packet->data, packet->len, FALSE);
2681 silc_buffer_free(packet);
2682 silc_free(channel_id);
2686 silc_server_command_free(cmd);
2689 /* Server side of CUMODE command. Changes client's mode on a channel. */
2691 SILC_SERVER_CMD_FUNC(cumode)
2693 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2694 SilcServer server = cmd->server;
2695 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2696 SilcChannelID *channel_id;
2697 SilcClientID *client_id;
2698 SilcChannelEntry channel;
2699 SilcClientEntry target_client;
2700 SilcChannelClientEntry chl;
2701 SilcBuffer packet, idp;
2702 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2703 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
2706 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2708 /* Get Channel ID */
2709 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2712 SILC_STATUS_ERR_NO_CHANNEL_ID);
2715 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
2717 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2718 SILC_STATUS_ERR_NO_CHANNEL_ID);
2722 /* Get channel entry */
2723 channel = silc_idlist_find_channel_by_id(server->local_list,
2726 channel = silc_idlist_find_channel_by_id(server->global_list,
2729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2730 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2735 /* Check whether sender is on the channel */
2736 if (!silc_server_client_on_channel(client, channel)) {
2737 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2738 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2742 /* Check that client has rights to change other's rights */
2743 silc_list_start(channel->user_list);
2744 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2745 if (chl->client == client) {
2746 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2747 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2748 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2749 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2753 sender_mask = chl->mode;
2758 /* Get the target client's channel mode mask */
2759 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2761 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2762 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2765 SILC_GET32_MSB(target_mask, tmp_mask);
2767 /* Get target Client ID */
2768 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2770 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2771 SILC_STATUS_ERR_NO_CLIENT_ID);
2774 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2776 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2777 SILC_STATUS_ERR_NO_CLIENT_ID);
2781 /* Get target client's entry */
2782 target_client = silc_idlist_find_client_by_id(server->local_list,
2784 if (!target_client) {
2785 target_client = silc_idlist_find_client_by_id(server->global_list,
2789 /* Check whether target client is on the channel */
2790 if (!silc_server_client_on_channel(target_client, channel)) {
2791 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2792 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2796 /* Get entry to the channel user list */
2797 silc_list_start(channel->user_list);
2798 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2799 if (chl->client == target_client)
2806 /* If the target client is founder, no one else can change their mode
2808 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2810 SILC_STATUS_ERR_NOT_YOU);
2814 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2815 /* Cannot promote anyone to channel founder */
2816 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2817 SILC_STATUS_ERR_NOT_YOU);
2820 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2821 if (target_client == client) {
2822 /* Remove channel founder rights from itself */
2823 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2827 SILC_STATUS_ERR_NOT_YOU);
2833 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2834 /* Promote to operator */
2835 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2836 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2840 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2841 /* Demote to normal user */
2842 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2847 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2849 /* Send notify to channel, notify only if mode was actually changed. */
2851 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2852 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2853 idp->data, idp->len,
2857 /* Set CUMODE notify type to network */
2858 if (!server->standalone)
2859 silc_server_send_notify_cumode(server, server->router->connection,
2860 server->server_type == SILC_ROUTER ?
2861 TRUE : FALSE, channel,
2862 target_mask, client->id,
2865 SILC_ID_CLIENT_LEN);
2868 /* Send command reply to sender */
2869 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2870 SILC_STATUS_OK, 0, 2,
2872 3, tmp_id, tmp_len);
2873 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2874 packet->data, packet->len, FALSE);
2876 silc_buffer_free(packet);
2877 silc_free(channel_id);
2878 silc_free(client_id);
2879 silc_buffer_free(idp);
2882 silc_server_command_free(cmd);
2885 /* Server side of KICK command. Kicks client out of channel. */
2887 SILC_SERVER_CMD_FUNC(kick)
2889 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2890 SilcServer server = cmd->server;
2891 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2892 SilcClientEntry target_client;
2893 SilcChannelID *channel_id;
2894 SilcClientID *client_id;
2895 SilcChannelEntry channel;
2896 SilcChannelClientEntry chl;
2898 unsigned int tmp_len;
2899 unsigned char *tmp, *comment;
2901 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
2903 /* Get Channel ID */
2904 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2907 SILC_STATUS_ERR_NO_CHANNEL_ID);
2910 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2912 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2913 SILC_STATUS_ERR_NO_CHANNEL_ID);
2917 /* Get channel entry */
2918 channel = silc_idlist_find_channel_by_id(server->local_list,
2921 channel = silc_idlist_find_channel_by_id(server->local_list,
2924 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2925 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2930 /* Check whether sender is on the channel */
2931 if (!silc_server_client_on_channel(client, channel)) {
2932 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2933 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2937 /* Check that the kicker is channel operator or channel founder */
2938 silc_list_start(channel->user_list);
2939 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2940 if (chl->client == client) {
2941 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2942 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2943 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2950 /* Get target Client ID */
2951 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2953 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2954 SILC_STATUS_ERR_NO_CLIENT_ID);
2957 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2959 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2960 SILC_STATUS_ERR_NO_CLIENT_ID);
2964 /* Get target client's entry */
2965 target_client = silc_idlist_find_client_by_id(server->local_list,
2967 if (!target_client) {
2968 target_client = silc_idlist_find_client_by_id(server->global_list,
2972 /* Check that the target client is not channel founder. Channel founder
2973 cannot be kicked from the channel. */
2974 silc_list_start(channel->user_list);
2975 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2976 if (chl->client == target_client) {
2977 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2978 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2979 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
2986 /* Check whether target client is on the channel */
2987 if (!silc_server_client_on_channel(target_client, channel)) {
2988 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2989 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2995 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2999 /* Send command reply to sender */
3000 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3003 /* Send KICKED notify to local clients on the channel */
3004 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3005 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3006 SILC_NOTIFY_TYPE_KICKED,
3008 idp->data, idp->len,
3009 comment, comment ? strlen(comment) : 0);
3010 silc_buffer_free(idp);
3012 /* Remove the client from the channel. If the channel does not exist
3013 after removing the client then the client kicked itself of the channel
3014 and we don't have to send anything after that. */
3015 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3016 target_client, FALSE))
3019 /* Send KICKED notify to primary route */
3020 if (!server->standalone)
3021 silc_server_send_notify_kicked(server, server->router->connection,
3022 server->server_type == SILC_ROUTER ?
3023 TRUE : FALSE, channel,
3024 target_client->id, SILC_ID_CLIENT_LEN,
3027 /* Re-generate channel key */
3028 silc_server_create_channel_key(server, channel, 0);
3030 /* Send the channel key to the channel. The key of course is not sent
3031 to the client who joined the channel. */
3032 silc_server_send_channel_key(server, target_client->connection, channel,
3033 server->server_type == SILC_ROUTER ?
3034 FALSE : !server->standalone);
3037 silc_server_command_free(cmd);
3040 SILC_SERVER_CMD_FUNC(oper)
3044 SILC_SERVER_CMD_FUNC(silcoper)
3048 /* Server side command of CONNECT. Connects us to the specified remote
3049 server or router. */
3051 SILC_SERVER_CMD_FUNC(connect)
3053 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3054 SilcServer server = cmd->server;
3055 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3057 unsigned int tmp_len;
3058 unsigned int port = SILC_PORT;
3060 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
3062 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3065 /* Check whether client has the permissions. */
3066 if (client->mode == SILC_UMODE_NONE) {
3067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3068 SILC_STATUS_ERR_NO_SERVER_PRIV);
3072 if (server->server_type == SILC_ROUTER &&
3073 client->mode & SILC_UMODE_SERVER_OPERATOR) {
3074 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3075 SILC_STATUS_ERR_NO_ROUTER_PRIV);
3079 /* Get the remote server */
3080 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3083 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3088 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3090 SILC_GET32_MSB(port, tmp);
3092 /* Create the connection. It is done with timeout and is async. */
3093 silc_server_create_connection(server, tmp, port);
3095 /* Send reply to the sender */
3096 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3100 silc_server_command_free(cmd);
3103 SILC_SERVER_CMD_FUNC(restart)
3107 /* Server side command of CLOSE. Closes connection to a specified server. */
3109 SILC_SERVER_CMD_FUNC(close)
3111 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3112 SilcServer server = cmd->server;
3113 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3114 SilcServerEntry server_entry;
3116 unsigned int tmp_len;
3117 unsigned char *name;
3118 unsigned int port = SILC_PORT;
3120 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3122 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3125 /* Check whether client has the permissions. */
3126 if (client->mode == SILC_UMODE_NONE) {
3127 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3128 SILC_STATUS_ERR_NO_SERVER_PRIV);
3132 /* Get the remote server */
3133 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3135 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3136 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3141 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3143 SILC_GET32_MSB(port, tmp);
3145 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3147 if (!server_entry) {
3148 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3149 SILC_STATUS_ERR_NO_SERVER_ID);
3153 /* Close the connection to the server */
3154 silc_server_free_sock_user_data(server, server_entry->connection);
3155 silc_server_disconnect_remote(server, server_entry->connection,
3156 "Server closed connection: "
3157 "Closed by operator");
3159 /* Send reply to the sender */
3160 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3164 silc_server_command_free(cmd);
3167 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3168 active connections. */
3170 SILC_SERVER_CMD_FUNC(shutdown)
3172 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3173 SilcServer server = cmd->server;
3174 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3176 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3178 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3181 /* Check whether client has the permission. */
3182 if (client->mode == SILC_UMODE_NONE) {
3183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3184 SILC_STATUS_ERR_NO_SERVER_PRIV);
3188 /* Then, gracefully, or not, bring the server down. */
3189 silc_server_stop(server);
3191 /* Send reply to the sender */
3192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3196 silc_server_command_free(cmd);
3199 /* Server side command of LEAVE. Removes client from a channel. */
3201 SILC_SERVER_CMD_FUNC(leave)
3203 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3204 SilcServer server = cmd->server;
3205 SilcSocketConnection sock = cmd->sock;
3206 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3208 SilcChannelEntry channel;
3210 unsigned int i, len;
3213 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3215 /* Get Channel ID */
3216 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3218 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3219 SILC_STATUS_ERR_NO_CHANNEL_ID);
3222 id = silc_id_payload_parse_id(tmp, len);
3224 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3225 SILC_STATUS_ERR_NO_CHANNEL_ID);
3229 /* Get channel entry */
3230 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3232 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3234 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3235 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3240 /* Check whether this client is on the channel */
3241 if (!silc_server_client_on_channel(id_entry, channel)) {
3242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3243 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3247 /* Notify routers that they should remove this client from their list
3248 of clients on the channel. Send LEAVE notify type. */
3249 if (!server->standalone)
3250 silc_server_send_notify_leave(server, server->router->connection,
3251 server->server_type == SILC_ROUTER ?
3252 TRUE : FALSE, channel, id_entry->id,
3253 SILC_ID_CLIENT_LEN);
3255 /* Remove client from channel */
3256 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3261 /* If the channel does not exist anymore we won't send anything */
3265 /* Re-generate channel key */
3266 silc_server_create_channel_key(server, channel, 0);
3268 /* Encode channel key payload to be distributed on the channel */
3270 silc_channel_key_payload_encode(len, tmp,
3271 strlen(channel->channel_key->cipher->name),
3272 channel->channel_key->cipher->name,
3273 channel->key_len / 8, channel->key);
3275 /* If we are normal server then we will send it to our router. If we
3276 are router we will send it to all local servers that has clients on
3278 if (server->server_type == SILC_SERVER) {
3279 if (!server->standalone)
3280 silc_server_packet_send(server,
3281 cmd->server->router->connection,
3282 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3283 packet->len, FALSE);
3288 /* Send to locally connected clients on the channel */
3289 silc_server_packet_send_local_channel(server, channel,
3290 SILC_PACKET_CHANNEL_KEY, 0,
3291 packet->data, packet->len, FALSE);
3293 silc_buffer_free(packet);
3297 silc_server_command_free(cmd);
3300 /* Server side of command USERS. Resolves clients and their USERS currently
3301 joined on the requested channel. The list of Client ID's and their modes
3302 on the channel is sent back. */
3304 SILC_SERVER_CMD_FUNC(users)
3306 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3307 SilcServer server = cmd->server;
3308 SilcChannelEntry channel;
3311 unsigned char *channel_id;
3312 unsigned int channel_id_len;
3313 SilcBuffer client_id_list;
3314 SilcBuffer client_mode_list;
3315 unsigned char lc[4];
3316 unsigned int list_count = 0;
3317 unsigned short ident = silc_command_get_ident(cmd->payload);
3319 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3321 /* Get Channel ID */
3322 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3325 SILC_STATUS_ERR_NO_CHANNEL_ID);
3328 id = silc_id_payload_parse_id(channel_id, channel_id_len);
3330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3331 SILC_STATUS_ERR_NO_CHANNEL_ID);
3335 /* If we are server and we don't know about this channel we will send
3336 the command to our router. If we know about the channel then we also
3337 have the list of users already. */
3338 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3340 if (server->server_type == SILC_SERVER && !server->standalone &&
3344 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3345 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3347 /* Send USERS command */
3348 silc_server_packet_send(server, server->router->connection,
3349 SILC_PACKET_COMMAND, cmd->packet->flags,
3350 tmpbuf->data, tmpbuf->len, TRUE);
3352 /* Reprocess this packet after received reply */
3353 silc_server_command_pending(server, SILC_COMMAND_USERS,
3354 silc_command_get_ident(cmd->payload),
3355 silc_server_command_destructor,
3356 silc_server_command_users,
3357 silc_server_command_dup(cmd));
3358 cmd->pending = TRUE;
3359 silc_command_set_ident(cmd->payload, ident);
3361 silc_buffer_free(tmpbuf);
3366 /* We are router and we will check the global list as well. */
3367 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3369 /* Channel really does not exist */
3370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3371 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3376 /* Get the users list */
3377 silc_server_get_users_on_channel(server, channel, &client_id_list,
3378 &client_mode_list, &list_count);
3381 SILC_PUT32_MSB(list_count, lc);
3384 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3385 SILC_STATUS_OK, 0, 4,
3386 2, channel_id, channel_id_len,
3388 4, client_id_list->data,
3389 client_id_list->len,
3390 5, client_mode_list->data,
3391 client_mode_list->len);
3392 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3393 packet->data, packet->len, FALSE);
3395 silc_buffer_free(packet);
3396 silc_buffer_free(client_id_list);
3397 silc_buffer_free(client_mode_list);
3401 silc_server_command_free(cmd);