5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
37 unsigned int arg_type,
39 unsigned int arg_len);
40 void silc_server_command_send_users(SilcServer server,
41 SilcSocketConnection sock,
42 SilcChannelEntry channel,
45 /* Server command list. */
46 SilcServerCommand silc_command_list[] =
48 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
49 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
54 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(connect, CONNECT,
59 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
60 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
62 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(restart, RESTART,
69 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
70 SILC_SERVER_CMD(close, CLOSE,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72 SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
73 SILC_SERVER_CMD(silcoper, SILCOPER,
74 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
75 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
76 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
81 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
83 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
85 SILC_LOG_DEBUG(("Start")); \
88 silc_server_command_send_status_reply(cmd, command, \
89 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
90 silc_server_command_free(cmd); \
94 silc_server_command_send_status_reply(cmd, command, \
95 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
96 silc_server_command_free(cmd); \
101 /* Returns TRUE if the connection is registered. Unregistered connections
102 usually cannot send commands hence the check. */
104 static int silc_server_is_registered(SilcServer server,
105 SilcSocketConnection sock,
106 SilcServerCommandContext cmd,
109 SilcIDListData idata = (SilcIDListData)sock->user_data;
110 if (idata->registered)
113 silc_server_command_send_status_reply(cmd, command,
114 SILC_STATUS_ERR_NOT_REGISTERED);
115 silc_server_command_free(cmd);
119 /* Processes received command packet. */
121 void silc_server_command_process(SilcServer server,
122 SilcSocketConnection sock,
123 SilcPacketContext *packet)
125 SilcServerCommandContext ctx;
126 SilcServerCommand *cmd;
129 /* XXX allow commands in but do not execute them more than once per
132 /* Check whether it is allowed for this connection to execute any
134 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
136 SilcClientEntry client = (SilcClientEntry)sock->user_data;
141 /* Allow only one command executed in 2 seconds. */
142 curtime = time(NULL);
143 if (client->last_command && (curtime - client->last_command) < 2)
146 /* Update access time */
147 client->last_command = curtime;
151 /* Allocate command context. This must be free'd by the
152 command routine receiving it. */
153 ctx = silc_server_command_alloc();
154 ctx->server = server;
155 ctx->sock = silc_socket_dup(sock);
156 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
158 /* Parse the command payload in the packet */
159 ctx->payload = silc_command_payload_parse(packet->buffer);
161 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
162 silc_buffer_free(packet->buffer);
163 silc_packet_context_free(packet);
167 ctx->args = silc_command_get_args(ctx->payload);
169 /* Execute command. If this fails the packet is dropped. */
170 for (cmd = silc_command_list; cmd->cb; cmd++)
171 if (cmd->cmd == silc_command_get(ctx->payload)) {
173 if (!(cmd->flags & SILC_CF_REG)) {
178 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
185 SILC_LOG_ERROR(("Unknown command, packet dropped"));
186 silc_server_command_free(ctx);
191 /* Allocate Command Context */
193 SilcServerCommandContext silc_server_command_alloc()
195 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
200 /* Free's the command context allocated before executing the command */
202 void silc_server_command_free(SilcServerCommandContext ctx)
205 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
207 if (ctx->users < 1) {
209 silc_command_free_payload(ctx->payload);
211 silc_packet_context_free(ctx->packet);
213 silc_socket_free(ctx->sock); /* Decrease reference counter */
218 /* Duplicate Command Context by adding reference counter. The context won't
219 be free'd untill it hits zero. */
221 SilcServerCommandContext
222 silc_server_command_dup(SilcServerCommandContext ctx)
225 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
230 /* Add new pending command to be executed when reply to a command has been
231 received. The `reply_cmd' is the command that will call the `callback'
232 with `context' when reply has been received. If `ident' is non-zero
233 the `callback' will be executed when received reply with command
234 identifier `ident'. */
236 void silc_server_command_pending(SilcServer server,
237 SilcCommand reply_cmd,
238 unsigned short ident,
239 SilcServerPendingDestructor destructor,
240 SilcCommandCb callback,
243 SilcServerCommandPending *reply;
245 reply = silc_calloc(1, sizeof(*reply));
246 reply->reply_cmd = reply_cmd;
247 reply->ident = ident;
248 reply->context = context;
249 reply->callback = callback;
250 reply->destructor = destructor;
251 silc_dlist_add(server->pending_commands, reply);
254 /* Deletes pending command by reply command type. */
256 void silc_server_command_pending_del(SilcServer server,
257 SilcCommand reply_cmd,
258 unsigned short ident)
260 SilcServerCommandPending *r;
262 silc_dlist_start(server->pending_commands);
263 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
264 if (r->reply_cmd == reply_cmd && r->ident == ident) {
265 silc_dlist_del(server->pending_commands, r);
271 /* Checks for pending commands and marks callbacks to be called from
272 the command reply function. Returns TRUE if there were pending command. */
274 int silc_server_command_pending_check(SilcServer server,
275 SilcServerCommandReplyContext ctx,
277 unsigned short ident)
279 SilcServerCommandPending *r;
281 silc_dlist_start(server->pending_commands);
282 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
283 if (r->reply_cmd == command && r->ident == ident) {
284 ctx->context = r->context;
285 ctx->callback = r->callback;
286 ctx->destructor = r->destructor;
295 /* Destructor function for pending callbacks. This is called when using
296 pending commands to free the context given for the pending command. */
298 static void silc_server_command_destructor(void *context)
300 silc_server_command_free((SilcServerCommandContext)context);
303 /* Sends simple status message as command reply packet */
306 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
308 SilcCommandStatus status)
312 SILC_LOG_DEBUG(("Sending command status %d", status));
314 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
315 silc_server_packet_send(cmd->server, cmd->sock,
316 SILC_PACKET_COMMAND_REPLY, 0,
317 buffer->data, buffer->len, FALSE);
318 silc_buffer_free(buffer);
321 /* Sends command status reply with one extra argument. The argument
322 type must be sent as argument. */
325 silc_server_command_send_status_data(SilcServerCommandContext cmd,
327 SilcCommandStatus status,
328 unsigned int arg_type,
330 unsigned int arg_len)
334 SILC_LOG_DEBUG(("Sending command status %d", status));
336 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
337 arg_type, arg, arg_len);
338 silc_server_packet_send(cmd->server, cmd->sock,
339 SILC_PACKET_COMMAND_REPLY, 0,
340 buffer->data, buffer->len, FALSE);
341 silc_buffer_free(buffer);
344 /******************************************************************************
348 ******************************************************************************/
351 silc_server_command_whois_parse(SilcServerCommandContext cmd,
352 SilcClientID ***client_id,
353 unsigned int *client_id_count,
361 unsigned int argc = silc_argument_get_arg_num(cmd->args);
364 /* If client ID is in the command it must be used instead of nickname */
365 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
367 /* No ID, get the nickname@server string and parse it. */
368 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
370 if (strchr(tmp, '@')) {
371 len = strcspn(tmp, "@");
372 *nickname = silc_calloc(len + 1, sizeof(char));
373 memcpy(*nickname, tmp, len);
374 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
375 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
377 *nickname = strdup(tmp);
380 silc_server_command_send_status_reply(cmd, command,
381 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
385 /* Command includes ID, we must use that. Also check whether the command
386 has more than one ID set - take them all. */
388 *client_id = silc_calloc(1, sizeof(**client_id));
389 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
390 if ((*client_id)[0] == NULL) {
391 silc_free(*client_id);
394 *client_id_count = 1;
396 /* Take all ID's from the command packet */
398 for (k = 1, i = 4; i < argc + 1; i++) {
399 tmp = silc_argument_get_arg_type(cmd->args, i, &len);
401 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
402 (*client_id_count + 1));
403 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
404 if ((*client_id)[k] == NULL) {
405 /* Cleanup all and fail */
406 for (i = 0; i < *client_id_count; i++)
407 silc_free((*client_id)[i]);
408 silc_free(*client_id);
411 (*client_id_count)++;
417 /* Command includes ID, use that */
420 /* Get the max count of reply messages allowed */
421 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
431 silc_server_command_whois_check(SilcServerCommandContext cmd,
432 SilcClientEntry *clients,
433 unsigned int clients_count)
435 SilcServer server = cmd->server;
437 SilcClientEntry entry;
439 for (i = 0; i < clients_count; i++) {
442 if (!entry->nickname || !entry->username) {
444 unsigned short old_ident;
449 old_ident = silc_command_get_ident(cmd->payload);
450 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
451 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
453 /* Send WHOIS command */
454 silc_server_packet_send(server, entry->router->connection,
455 SILC_PACKET_COMMAND, cmd->packet->flags,
456 tmpbuf->data, tmpbuf->len, TRUE);
458 /* Reprocess this packet after received reply */
459 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
460 silc_command_get_ident(cmd->payload),
461 silc_server_command_destructor,
462 silc_server_command_whois,
463 silc_server_command_dup(cmd));
466 silc_command_set_ident(cmd->payload, old_ident);
468 silc_buffer_free(tmpbuf);
477 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
478 SilcClientEntry *clients,
479 unsigned int clients_count)
481 SilcServer server = cmd->server;
483 int i, count = 0, len;
484 SilcBuffer packet, idp;
485 SilcClientEntry entry;
486 SilcCommandStatus status;
487 unsigned short ident = silc_command_get_ident(cmd->payload);
489 status = SILC_STATUS_OK;
490 if (clients_count > 1)
491 status = SILC_STATUS_LIST_START;
493 for (i = 0; i < clients_count; i++) {
496 if (count && i - 1 == count)
499 if (clients_count > 2)
500 status = SILC_STATUS_LIST_ITEM;
502 if (clients_count > 1 && i == clients_count - 1)
503 status = SILC_STATUS_LIST_END;
505 /* Sanity check, however these should never fail. However, as
506 this sanity check has been added here they have failed. */
507 if (!entry->nickname || !entry->username)
510 /* Send WHOIS reply */
511 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
512 tmp = silc_argument_get_first_arg(cmd->args, NULL);
516 char nh[256], uh[256];
517 unsigned char idle[4];
518 SilcSocketConnection hsock;
520 memset(uh, 0, sizeof(uh));
521 memset(nh, 0, sizeof(nh));
523 strncat(nh, entry->nickname, strlen(entry->nickname));
524 if (!strchr(entry->nickname, '@')) {
526 len = entry->router ? strlen(entry->router->server_name) :
527 strlen(server->server_name);
528 strncat(nh, entry->router ? entry->router->server_name :
529 server->server_name, len);
532 strncat(uh, entry->username, strlen(entry->username));
533 if (!strchr(entry->username, '@')) {
535 hsock = (SilcSocketConnection)entry->connection;
536 len = strlen(hsock->hostname);
537 strncat(uh, hsock->hostname, len);
540 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
545 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
547 2, idp->data, idp->len,
551 strlen(entry->userinfo),
555 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
557 2, idp->data, idp->len,
563 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
564 0, packet->data, packet->len, FALSE);
566 silc_buffer_free(packet);
567 silc_buffer_free(idp);
572 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
574 SilcServer server = cmd->server;
575 char *nick = NULL, *server_name = NULL;
576 int count = 0, clients_count = 0;
577 SilcClientEntry *clients = NULL, entry;
578 SilcClientID **client_id = NULL;
579 unsigned int client_id_count = 0;
582 /* Protocol dictates that we must always send the received WHOIS request
583 to our router if we are normal server, so let's do it now unless we
584 are standalone. We will not send any replies to the client until we
585 have received reply from the router. */
586 if (server->server_type == SILC_SERVER &&
587 !cmd->pending && !server->standalone) {
589 unsigned short old_ident;
591 old_ident = silc_command_get_ident(cmd->payload);
592 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
593 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
595 /* Send WHOIS command to our router */
596 silc_server_packet_send(server, (SilcSocketConnection)
597 server->router->connection,
598 SILC_PACKET_COMMAND, cmd->packet->flags,
599 tmpbuf->data, tmpbuf->len, TRUE);
601 /* Reprocess this packet after received reply from router */
602 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
603 silc_command_get_ident(cmd->payload),
604 silc_server_command_destructor,
605 silc_server_command_whois,
606 silc_server_command_dup(cmd));
609 silc_command_set_ident(cmd->payload, old_ident);
611 silc_buffer_free(tmpbuf);
616 /* We are ready to process the command request. Let's search for the
617 requested client and send reply to the requesting client. */
619 /* Parse the whois request */
620 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
621 &nick, &server_name, &count,
625 /* Get all clients matching that ID or nickname from local list */
626 if (client_id_count) {
627 /* Check all Client ID's received in the command packet */
628 for (i = 0; i < client_id_count; i++) {
629 entry = silc_idlist_find_client_by_id(server->local_list,
632 clients = silc_realloc(clients, sizeof(*clients) *
633 (clients_count + 1));
634 clients[clients_count++] = entry;
638 clients = silc_idlist_get_clients_by_nickname(server->local_list,
643 /* Check global list as well */
645 if (client_id_count) {
646 /* Check all Client ID's received in the command packet */
647 for (i = 0; i < client_id_count; i++) {
648 entry = silc_idlist_find_client_by_id(server->global_list,
651 clients = silc_realloc(clients, sizeof(*clients) *
652 (clients_count + 1));
653 clients[clients_count++] = entry;
657 clients = silc_idlist_get_clients_by_nickname(server->global_list,
664 /* Such client(s) really does not exist in the SILC network. */
665 if (!client_id_count) {
666 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
667 SILC_STATUS_ERR_NO_SUCH_NICK,
668 3, nick, strlen(nick));
670 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
671 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
672 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
673 2, idp->data, idp->len);
674 silc_buffer_free(idp);
679 /* Router always finds the client entry if it exists in the SILC network.
680 However, it might be incomplete entry and does not include all the
681 mandatory fields that WHOIS command reply requires. Check for these and
682 make query from the server who owns the client if some fields are
684 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
689 /* Send the command reply to the client */
690 silc_server_command_whois_send_reply(cmd, clients, clients_count);
693 if (client_id_count) {
694 for (i = 0; i < client_id_count; i++)
695 silc_free(client_id[i]);
696 silc_free(client_id);
703 silc_free(server_name);
709 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
711 SilcServer server = cmd->server;
712 char *nick = NULL, *server_name = NULL;
713 int count = 0, clients_count = 0;
714 SilcClientEntry *clients = NULL, entry;
715 SilcClientID **client_id = NULL;
716 unsigned int client_id_count = 0;
719 /* Parse the whois request */
720 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
721 &nick, &server_name, &count,
725 /* Process the command request. Let's search for the requested client and
726 send reply to the requesting server. */
728 if (client_id_count) {
729 /* Check all Client ID's received in the command packet */
730 for (i = 0; i < client_id_count; i++) {
731 entry = silc_idlist_find_client_by_id(server->local_list,
734 clients = silc_realloc(clients, sizeof(*clients) *
735 (clients_count + 1));
736 clients[clients_count++] = entry;
740 clients = silc_idlist_get_clients_by_nickname(server->local_list,
744 clients = silc_idlist_get_clients_by_hash(server->local_list,
745 nick, server->md5hash,
749 /* If we are router we will check our global list as well. */
750 if (!clients && server->server_type == SILC_ROUTER) {
751 if (client_id_count) {
752 /* Check all Client ID's received in the command packet */
753 for (i = 0; i < client_id_count; i++) {
754 entry = silc_idlist_find_client_by_id(server->global_list,
757 clients = silc_realloc(clients, sizeof(*clients) *
758 (clients_count + 1));
759 clients[clients_count++] = entry;
763 clients = silc_idlist_get_clients_by_nickname(server->global_list,
767 clients = silc_idlist_get_clients_by_hash(server->global_list,
768 nick, server->md5hash,
774 /* Such a client really does not exist in the SILC network. */
775 if (!client_id_count) {
776 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
777 SILC_STATUS_ERR_NO_SUCH_NICK,
778 3, nick, strlen(nick));
780 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
781 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
782 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
783 2, idp->data, idp->len);
784 silc_buffer_free(idp);
789 /* Router always finds the client entry if it exists in the SILC network.
790 However, it might be incomplete entry and does not include all the
791 mandatory fields that WHOIS command reply requires. Check for these and
792 make query from the server who owns the client if some fields are
794 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
799 /* Send the command reply to the client */
800 silc_server_command_whois_send_reply(cmd, clients, clients_count);
803 if (client_id_count) {
804 for (i = 0; i < client_id_count; i++)
805 silc_free(client_id[i]);
806 silc_free(client_id);
813 silc_free(server_name);
818 /* Server side of command WHOIS. Processes user's query and sends found
819 results as command replies back to the client. */
821 SILC_SERVER_CMD_FUNC(whois)
823 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
826 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
828 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
829 ret = silc_server_command_whois_from_client(cmd);
830 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
831 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
832 ret = silc_server_command_whois_from_server(cmd);
835 silc_server_command_free(cmd);
838 SILC_SERVER_CMD_FUNC(whowas)
842 /******************************************************************************
846 ******************************************************************************/
848 /* Checks that all mandatory fields are present. If not then send WHOIS
849 request to the server who owns the client. We use WHOIS because we want
850 to get as much information as possible at once. */
853 silc_server_command_identify_check(SilcServerCommandContext cmd,
854 SilcClientEntry *clients,
855 unsigned int clients_count)
857 SilcServer server = cmd->server;
859 SilcClientEntry entry;
861 for (i = 0; i < clients_count; i++) {
864 if (!entry->nickname) {
866 unsigned short old_ident;
871 old_ident = silc_command_get_ident(cmd->payload);
872 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
873 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
874 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
876 /* Send WHOIS request. We send WHOIS since we're doing the requesting
877 now anyway so make it a good one. */
878 silc_server_packet_send(server, entry->router->connection,
879 SILC_PACKET_COMMAND, cmd->packet->flags,
880 tmpbuf->data, tmpbuf->len, TRUE);
882 /* Reprocess this packet after received reply */
883 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
884 silc_command_get_ident(cmd->payload),
885 silc_server_command_destructor,
886 silc_server_command_identify,
887 silc_server_command_dup(cmd));
891 /* Put old data back to the Command Payload we just changed */
892 silc_command_set_ident(cmd->payload, old_ident);
893 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
895 silc_buffer_free(tmpbuf);
904 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
905 SilcClientEntry *clients,
906 unsigned int clients_count)
908 SilcServer server = cmd->server;
910 int i, count = 0, len;
911 SilcBuffer packet, idp;
912 SilcClientEntry entry;
913 SilcCommandStatus status;
914 unsigned short ident = silc_command_get_ident(cmd->payload);
916 status = SILC_STATUS_OK;
917 if (clients_count > 1)
918 status = SILC_STATUS_LIST_START;
920 for (i = 0; i < clients_count; i++) {
923 if (count && i - 1 == count)
926 if (clients_count > 2)
927 status = SILC_STATUS_LIST_ITEM;
929 if (clients_count > 1 && i == clients_count - 1)
930 status = SILC_STATUS_LIST_END;
932 /* Send IDENTIFY reply */
933 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
934 tmp = silc_argument_get_first_arg(cmd->args, NULL);
938 char nh[256], uh[256];
939 SilcSocketConnection hsock;
941 memset(uh, 0, sizeof(uh));
942 memset(nh, 0, sizeof(nh));
944 strncat(nh, entry->nickname, strlen(entry->nickname));
945 if (!strchr(entry->nickname, '@')) {
947 len = entry->router ? strlen(entry->router->server_name) :
948 strlen(server->server_name);
949 strncat(nh, entry->router ? entry->router->server_name :
950 server->server_name, len);
953 if (!entry->username) {
954 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
955 SILC_STATUS_OK, ident, 2,
956 2, idp->data, idp->len,
959 strncat(uh, entry->username, strlen(entry->username));
960 if (!strchr(entry->username, '@')) {
962 hsock = (SilcSocketConnection)entry->connection;
963 len = strlen(hsock->hostname);
964 strncat(uh, hsock->hostname, len);
967 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
968 SILC_STATUS_OK, ident, 3,
969 2, idp->data, idp->len,
974 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
975 0, packet->data, packet->len, FALSE);
977 silc_buffer_free(packet);
978 silc_buffer_free(idp);
984 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
986 SilcServer server = cmd->server;
987 char *nick = NULL, *server_name = NULL;
988 int count = 0, clients_count = 0;
989 SilcClientEntry *clients = NULL, entry;
990 SilcClientID **client_id = NULL;
991 unsigned int client_id_count = 0;
994 /* Protocol dictates that we must always send the received IDENTIFY request
995 to our router if we are normal server, so let's do it now unless we
996 are standalone. We will not send any replies to the client until we
997 have received reply from the router. */
998 if (server->server_type == SILC_SERVER &&
999 !cmd->pending && !server->standalone) {
1001 unsigned short old_ident;
1003 old_ident = silc_command_get_ident(cmd->payload);
1004 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1005 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1007 /* Send IDENTIFY command to our router */
1008 silc_server_packet_send(server, (SilcSocketConnection)
1009 server->router->connection,
1010 SILC_PACKET_COMMAND, cmd->packet->flags,
1011 tmpbuf->data, tmpbuf->len, TRUE);
1013 /* Reprocess this packet after received reply from router */
1014 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1015 silc_command_get_ident(cmd->payload),
1016 silc_server_command_destructor,
1017 silc_server_command_identify,
1018 silc_server_command_dup(cmd));
1019 cmd->pending = TRUE;
1021 silc_command_set_ident(cmd->payload, old_ident);
1023 silc_buffer_free(tmpbuf);
1028 /* We are ready to process the command request. Let's search for the
1029 requested client and send reply to the requesting client. */
1031 /* Parse the IDENTIFY request */
1032 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1033 &nick, &server_name, &count,
1034 SILC_COMMAND_IDENTIFY))
1037 /* Get all clients matching that ID or nickname from local list */
1038 if (client_id_count) {
1039 /* Check all Client ID's received in the command packet */
1040 for (i = 0; i < client_id_count; i++) {
1041 entry = silc_idlist_find_client_by_id(server->local_list,
1042 client_id[i], NULL);
1044 clients = silc_realloc(clients, sizeof(*clients) *
1045 (clients_count + 1));
1046 clients[clients_count++] = entry;
1050 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1055 /* Check global list as well */
1057 if (client_id_count) {
1058 /* Check all Client ID's received in the command packet */
1059 for (i = 0; i < client_id_count; i++) {
1060 entry = silc_idlist_find_client_by_id(server->global_list,
1061 client_id[i], NULL);
1063 clients = silc_realloc(clients, sizeof(*clients) *
1064 (clients_count + 1));
1065 clients[clients_count++] = entry;
1069 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1076 /* Such a client really does not exist in the SILC network. */
1077 if (!client_id_count) {
1078 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1079 SILC_STATUS_ERR_NO_SUCH_NICK,
1080 3, nick, strlen(nick));
1082 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1083 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1084 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1085 2, idp->data, idp->len);
1086 silc_buffer_free(idp);
1091 /* Check that all mandatory fields are present and request those data
1092 from the server who owns the client if necessary. */
1093 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1098 /* Send the command reply to the client */
1099 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1102 if (client_id_count) {
1103 for (i = 0; i < client_id_count; i++)
1104 silc_free(client_id[i]);
1105 silc_free(client_id);
1112 silc_free(server_name);
1118 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1120 SilcServer server = cmd->server;
1121 char *nick = NULL, *server_name = NULL;
1122 int count = 0, clients_count = 0;
1123 SilcClientEntry *clients = NULL, entry;
1124 SilcClientID **client_id = NULL;
1125 unsigned int client_id_count = 0;
1128 /* Parse the IDENTIFY request */
1129 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1130 &nick, &server_name, &count,
1131 SILC_COMMAND_IDENTIFY))
1134 /* Process the command request. Let's search for the requested client and
1135 send reply to the requesting server. */
1137 if (client_id_count) {
1138 /* Check all Client ID's received in the command packet */
1139 for (i = 0; i < client_id_count; i++) {
1140 entry = silc_idlist_find_client_by_id(server->local_list,
1141 client_id[i], NULL);
1143 clients = silc_realloc(clients, sizeof(*clients) *
1144 (clients_count + 1));
1145 clients[clients_count++] = entry;
1149 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1153 clients = silc_idlist_get_clients_by_hash(server->local_list,
1154 nick, server->md5hash,
1158 /* If we are router we will check our global list as well. */
1159 if (!clients && server->server_type == SILC_ROUTER) {
1160 if (client_id_count) {
1161 /* Check all Client ID's received in the command packet */
1162 for (i = 0; i < client_id_count; i++) {
1163 entry = silc_idlist_find_client_by_id(server->global_list,
1164 client_id[i], NULL);
1166 clients = silc_realloc(clients, sizeof(*clients) *
1167 (clients_count + 1));
1168 clients[clients_count++] = entry;
1172 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1176 clients = silc_idlist_get_clients_by_hash(server->global_list,
1177 nick, server->md5hash,
1183 /* Such a client really does not exist in the SILC network. */
1184 if (!client_id_count) {
1185 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1186 SILC_STATUS_ERR_NO_SUCH_NICK,
1187 3, nick, strlen(nick));
1189 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1190 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1191 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1192 2, idp->data, idp->len);
1193 silc_buffer_free(idp);
1198 /* Check that all mandatory fields are present and request those data
1199 from the server who owns the client if necessary. */
1200 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1205 /* Send the command reply */
1206 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1209 if (client_id_count) {
1210 for (i = 0; i < client_id_count; i++)
1211 silc_free(client_id[i]);
1212 silc_free(client_id);
1219 silc_free(server_name);
1224 SILC_SERVER_CMD_FUNC(identify)
1226 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1229 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1231 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1232 ret = silc_server_command_identify_from_client(cmd);
1233 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1234 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1235 ret = silc_server_command_identify_from_server(cmd);
1238 silc_server_command_free(cmd);
1241 /* Checks string for bad characters and returns TRUE if they are found. */
1243 static int silc_server_command_bad_chars(char *nick)
1245 if (strchr(nick, '\\')) return TRUE;
1246 if (strchr(nick, '\"')) return TRUE;
1247 if (strchr(nick, '´')) return TRUE;
1248 if (strchr(nick, '`')) return TRUE;
1249 if (strchr(nick, '\'')) return TRUE;
1250 if (strchr(nick, '*')) return TRUE;
1251 if (strchr(nick, '/')) return TRUE;
1252 if (strchr(nick, '@')) return TRUE;
1257 /* Server side of command NICK. Sets nickname for user. Setting
1258 nickname causes generation of a new client ID for the client. The
1259 new client ID is sent to the client after changing the nickname. */
1261 SILC_SERVER_CMD_FUNC(nick)
1263 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1264 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1265 SilcServer server = cmd->server;
1266 SilcBuffer packet, nidp, oidp;
1267 SilcClientID *new_id;
1270 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1272 /* Check nickname */
1273 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1274 if (silc_server_command_bad_chars(nick) == TRUE) {
1275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1276 SILC_STATUS_ERR_BAD_NICKNAME);
1280 /* Create new Client ID */
1281 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1282 cmd->server->md5hash, nick,
1285 /* Send notify about nickname change to our router. We send the new
1286 ID and ask to replace it with the old one. If we are router the
1287 packet is broadcasted. */
1288 if (!server->standalone)
1289 silc_server_send_replace_id(server, server->router->connection,
1290 server->server_type == SILC_SERVER ?
1291 FALSE : TRUE, client->id,
1292 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1293 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1295 /* Remove old cache entry */
1296 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1299 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1303 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1304 silc_free(client->id);
1307 /* Save the nickname as this client is our local client */
1308 if (client->nickname)
1309 silc_free(client->nickname);
1311 client->nickname = strdup(nick);
1312 client->id = new_id;
1314 /* Update client cache */
1315 silc_idcache_add(server->local_list->clients, client->nickname,
1316 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1318 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1320 /* Send NICK_CHANGE notify */
1321 silc_server_send_notify_on_channels(server, client,
1322 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1323 oidp->data, oidp->len,
1324 nidp->data, nidp->len);
1326 /* Send the new Client ID as reply command back to client */
1327 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1328 SILC_STATUS_OK, 0, 1,
1329 2, nidp->data, nidp->len);
1330 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1331 0, packet->data, packet->len, FALSE);
1333 silc_buffer_free(packet);
1334 silc_buffer_free(nidp);
1335 silc_buffer_free(oidp);
1338 silc_server_command_free(cmd);
1341 SILC_SERVER_CMD_FUNC(list)
1345 /* Server side of TOPIC command. Sets topic for channel and/or returns
1346 current topic to client. */
1348 SILC_SERVER_CMD_FUNC(topic)
1350 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1351 SilcServer server = cmd->server;
1352 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1353 SilcChannelID *channel_id;
1354 SilcChannelEntry channel;
1355 SilcChannelClientEntry chl;
1356 SilcBuffer packet, idp;
1358 unsigned int argc, tmp_len;
1360 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1362 argc = silc_argument_get_arg_num(cmd->args);
1364 /* Get Channel ID */
1365 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1367 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1368 SILC_STATUS_ERR_NO_CHANNEL_ID);
1371 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1374 SILC_STATUS_ERR_NO_CHANNEL_ID);
1378 /* Check whether the channel exists */
1379 channel = silc_idlist_find_channel_by_id(server->local_list,
1382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1383 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1389 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1391 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1392 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1396 if (strlen(tmp) > 256) {
1397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1398 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1402 /* See whether has rights to change topic */
1403 silc_list_start(channel->user_list);
1404 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1405 if (chl->client == client) {
1406 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1408 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1416 /* Set the topic for channel */
1418 silc_free(channel->topic);
1419 channel->topic = strdup(tmp);
1421 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1423 /* Send notify about topic change to all clients on the channel */
1424 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1425 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1426 idp->data, idp->len,
1427 channel->topic, strlen(channel->topic));
1428 silc_buffer_free(idp);
1431 /* Send the topic to client as reply packet */
1432 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1434 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1435 SILC_STATUS_OK, 0, 2,
1436 2, idp->data, idp->len,
1438 strlen(channel->topic));
1440 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1441 SILC_STATUS_OK, 0, 1,
1442 2, idp->data, idp->len);
1443 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1444 0, packet->data, packet->len, FALSE);
1446 silc_buffer_free(packet);
1447 silc_buffer_free(idp);
1448 silc_free(channel_id);
1451 silc_server_command_free(cmd);
1454 /* Server side of INVITE command. Invites some client to join some channel. */
1456 SILC_SERVER_CMD_FUNC(invite)
1458 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1459 SilcServer server = cmd->server;
1460 SilcSocketConnection sock = cmd->sock, dest_sock;
1461 SilcClientEntry sender, dest;
1462 SilcClientID *dest_id;
1463 SilcChannelEntry channel;
1464 SilcChannelID *channel_id;
1469 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1471 /* Get destination ID */
1472 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1474 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1475 SILC_STATUS_ERR_NO_CLIENT_ID);
1478 dest_id = silc_id_payload_parse_id(tmp, len);
1480 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1481 SILC_STATUS_ERR_NO_CLIENT_ID);
1485 /* Get Channel ID */
1486 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1489 SILC_STATUS_ERR_NO_CHANNEL_ID);
1492 channel_id = silc_id_payload_parse_id(tmp, len);
1494 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1495 SILC_STATUS_ERR_NO_CHANNEL_ID);
1499 /* Check whether the channel exists */
1500 channel = silc_idlist_find_channel_by_id(server->local_list,
1503 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1504 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1508 /* Check whether the sender of this command is on the channel. */
1509 sender = (SilcClientEntry)sock->user_data;
1510 if (!silc_server_client_on_channel(sender, channel)) {
1511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1512 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1516 /* Check whether the channel is invite-only channel. If yes then the
1517 sender of this command must be at least channel operator. */
1518 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1519 SilcChannelClientEntry chl;
1521 silc_list_start(channel->user_list);
1522 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1523 if (chl->client == sender) {
1524 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1525 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1526 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1533 /* Find the connection data for the destination. If it is local we will
1534 send it directly otherwise we will send it to router for routing. */
1535 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1537 dest_sock = (SilcSocketConnection)dest->connection;
1539 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1541 /* Check whether the requested client is already on the channel. */
1542 /* XXX if we are normal server we don't know about global clients on
1543 the channel thus we must request it (USERS command), check from
1544 local cache as well. */
1545 if (silc_server_client_on_channel(dest, channel)) {
1546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1547 SILC_STATUS_ERR_USER_ON_CHANNEL);
1551 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1553 /* Send notify to the client that is invited to the channel */
1554 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1555 SILC_NOTIFY_TYPE_INVITE, 2,
1556 sidp->data, sidp->len, tmp, len);
1558 /* Send command reply */
1559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1562 silc_buffer_free(sidp);
1565 silc_server_command_free(cmd);
1568 /* Quits connection to client. This gets called if client won't
1569 close the connection even when it has issued QUIT command. */
1571 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1573 SilcServer server = (SilcServer)context;
1574 SilcSocketConnection sock = server->sockets[fd];
1576 /* Free all client specific data, such as client entry and entires
1577 on channels this client may be on. */
1578 silc_server_free_sock_user_data(server, sock);
1580 /* Close the connection on our side */
1581 silc_server_close_connection(server, sock);
1584 /* Quits SILC session. This is the normal way to disconnect client. */
1586 SILC_SERVER_CMD_FUNC(quit)
1588 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1589 SilcServer server = cmd->server;
1590 SilcSocketConnection sock = cmd->sock;
1592 SILC_LOG_DEBUG(("Start"));
1594 /* We quit the connection with little timeout */
1595 silc_task_register(server->timeout_queue, sock->sock,
1596 silc_server_command_quit_cb, server,
1597 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1599 silc_server_command_free(cmd);
1602 SILC_SERVER_CMD_FUNC(kill)
1606 /* Server side of command INFO. This sends information about us to
1607 the client. If client requested specific server we will send the
1608 command to that server. */
1610 SILC_SERVER_CMD_FUNC(info)
1612 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1613 SilcServer server = cmd->server;
1614 SilcBuffer packet, idp;
1615 char info_string[256], *dest_server;
1617 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1619 /* Get server name */
1620 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1622 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1623 SILC_STATUS_ERR_NO_SUCH_SERVER);
1627 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1628 /* Send our reply */
1629 memset(info_string, 0, sizeof(info_string));
1630 snprintf(info_string, sizeof(info_string),
1631 "location: %s server: %s admin: %s <%s>",
1632 server->config->admin_info->location,
1633 server->config->admin_info->server_type,
1634 server->config->admin_info->admin_name,
1635 server->config->admin_info->admin_email);
1637 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1639 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1640 SILC_STATUS_OK, 0, 2,
1641 2, idp->data, idp->len,
1643 strlen(info_string));
1644 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1645 packet->data, packet->len, FALSE);
1647 silc_buffer_free(packet);
1648 silc_buffer_free(idp);
1650 /* Send this command to the requested server */
1652 if (server->server_type == SILC_SERVER && !server->standalone) {
1656 if (server->server_type == SILC_ROUTER) {
1662 silc_server_command_free(cmd);
1665 SILC_SERVER_CMD_FUNC(connect)
1669 /* Server side of command PING. This just replies to the ping. */
1671 SILC_SERVER_CMD_FUNC(ping)
1673 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1674 SilcServer server = cmd->server;
1679 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1682 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1685 SILC_STATUS_ERR_NO_SERVER_ID);
1688 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1692 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1693 /* Send our reply */
1694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1697 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1698 SILC_STATUS_ERR_NO_SUCH_SERVER);
1705 silc_server_command_free(cmd);
1708 SILC_SERVER_CMD_FUNC(oper)
1712 /* Assembles USERS command and executes it. This is called when client
1713 joins to a channel and we wan't to send USERS command reply to the
1716 void silc_server_command_send_users(SilcServer server,
1717 SilcSocketConnection sock,
1718 SilcChannelEntry channel,
1721 SilcServerCommandContext cmd;
1722 SilcBuffer buffer, idp;
1723 SilcPacketContext *packet = silc_packet_context_alloc();
1725 SILC_LOG_DEBUG(("Start"));
1727 /* Create USERS command packet and process it. */
1728 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1729 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1730 1, idp->data, idp->len);
1732 packet->buffer = silc_buffer_copy(buffer);
1733 packet->sock = sock;
1734 packet->type = SILC_PACKET_COMMAND;
1736 cmd = silc_server_command_alloc();
1737 cmd->payload = silc_command_payload_parse(buffer);
1738 if (!cmd->payload) {
1740 silc_buffer_free(buffer);
1741 silc_buffer_free(idp);
1742 silc_packet_context_free(packet);
1745 cmd->args = silc_command_get_args(cmd->payload);
1746 cmd->server = server;
1747 cmd->sock = silc_socket_dup(sock);
1748 cmd->packet = silc_packet_context_dup(packet);
1749 cmd->pending = FALSE;
1752 /* If this function was called from pending command then instead of
1753 processing the command now, register a pending command callback which
1754 will process it after we've received the automatic USERS command
1756 silc_server_command_pending(server, SILC_COMMAND_USERS, 0,
1757 silc_server_command_destructor,
1758 silc_server_command_users,
1759 silc_server_command_dup(cmd));
1760 cmd->pending = TRUE;
1761 silc_buffer_free(buffer);
1762 silc_buffer_free(idp);
1766 /* Process USERS command. */
1767 silc_server_command_users((void *)cmd);
1769 silc_buffer_free(buffer);
1770 silc_buffer_free(idp);
1771 silc_packet_context_free(packet);
1774 /* Internal routine to join channel. The channel sent to this function
1775 has been either created or resolved from ID lists. This joins the sent
1776 client to the channel. */
1778 static void silc_server_command_join_channel(SilcServer server,
1779 SilcServerCommandContext cmd,
1780 SilcChannelEntry channel,
1781 SilcClientID *client_id,
1785 SilcSocketConnection sock = cmd->sock;
1787 unsigned int tmp_len;
1788 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1789 SilcClientEntry client;
1790 SilcChannelClientEntry chl;
1791 SilcBuffer reply, chidp, clidp, keyp;
1792 unsigned short ident = silc_command_get_ident(cmd->payload);
1794 SILC_LOG_DEBUG(("Start"));
1799 /* Get passphrase */
1800 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1802 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1803 memcpy(passphrase, tmp, tmp_len);
1807 * Check channel modes
1810 /* Check invite list if channel is invite-only channel */
1811 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1812 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1813 /* Invite list is specified. Check whether client is invited in the
1814 list. If not, then check whether it has been invited otherwise. */
1817 /* XXX client must be invited to be able to join the channel */
1821 /* Check ban list if set */
1822 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1826 /* Check the channel passphrase if set. */
1827 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1828 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1829 strlen(channel->mode_data.passphrase))) {
1830 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1831 SILC_STATUS_ERR_BAD_PASSWORD);
1836 /* Check user count limit if set. */
1837 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1838 if (silc_list_count(channel->user_list) + 1 >
1839 channel->mode_data.user_limit) {
1840 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1841 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1847 * Client is allowed to join to the channel. Make it happen.
1850 /* Get the client entry */
1851 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1852 client = (SilcClientEntry)sock->user_data;
1854 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1857 /* XXX actually this is useless since router finds always cell's
1858 local clients from its local lists. */
1859 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1866 /* Check whether the client already is on the channel */
1867 if (silc_server_client_on_channel(client, channel)) {
1868 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1869 SILC_STATUS_ERR_USER_ON_CHANNEL);
1873 /* Generate new channel key as protocol dictates */
1874 if (!created || !channel->channel_key)
1875 silc_server_create_channel_key(server, channel, 0);
1877 /* Send the channel key. This is broadcasted to the channel but is not
1878 sent to the client who is joining to the channel. */
1879 silc_server_send_channel_key(server, NULL, channel,
1880 server->server_type == SILC_ROUTER ?
1881 FALSE : server->standalone);
1883 /* Join the client to the channel by adding it to channel's user list.
1884 Add also the channel to client entry's channels list for fast cross-
1886 chl = silc_calloc(1, sizeof(*chl));
1888 chl->client = client;
1889 chl->channel = channel;
1890 silc_list_add(channel->user_list, chl);
1891 silc_list_add(client->channels, chl);
1893 /* Encode Client ID Payload of the original client who wants to join */
1894 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1896 /* Encode command reply packet */
1897 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1898 SILC_PUT32_MSB(channel->mode, mode);
1899 SILC_PUT32_MSB(created, tmp2);
1900 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1901 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1902 SILC_ID_CHANNEL_LEN,
1903 channel->channel_key->cipher->name,
1904 channel->key_len / 8, channel->key);
1906 if (!channel->topic) {
1908 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1909 SILC_STATUS_OK, ident, 5,
1910 2, channel->channel_name,
1911 strlen(channel->channel_name),
1912 3, chidp->data, chidp->len,
1915 6, keyp->data, keyp->len);
1918 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1919 SILC_STATUS_OK, ident, 6,
1920 2, channel->channel_name,
1921 strlen(channel->channel_name),
1922 3, chidp->data, chidp->len,
1925 6, keyp->data, keyp->len,
1927 strlen(channel->topic));
1930 /* Send command reply */
1931 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1932 reply->data, reply->len, FALSE);
1934 if (!cmd->pending) {
1935 /* Send JOIN notify to locally connected clients on the channel */
1936 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1937 SILC_NOTIFY_TYPE_JOIN, 1,
1938 clidp->data, clidp->len);
1940 /* Send NEW_CHANNEL_USER packet to our primary router */
1941 if (!server->standalone)
1942 silc_server_send_new_channel_user(server, server->router->connection,
1943 server->server_type == SILC_SERVER ?
1945 channel->id, SILC_ID_CHANNEL_LEN,
1946 client->id, SILC_ID_CLIENT_LEN);
1949 /* Send USERS command reply to the joined channel so the user sees who
1950 is currently on the channel. */
1951 silc_server_command_send_users(server, sock, channel, cmd->pending);
1953 silc_buffer_free(reply);
1954 silc_buffer_free(clidp);
1955 silc_buffer_free(chidp);
1956 silc_buffer_free(keyp);
1960 silc_free(passphrase);
1963 /* Server side of command JOIN. Joins client into requested channel. If
1964 the channel does not exist it will be created. */
1966 SILC_SERVER_CMD_FUNC(join)
1968 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1969 SilcServer server = cmd->server;
1971 char *tmp, *channel_name = NULL, *cipher = NULL;
1972 SilcChannelEntry channel;
1973 unsigned int umode = 0;
1974 int created = FALSE;
1975 SilcClientID *client_id;
1977 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1979 /* Get channel name */
1980 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1983 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1988 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1989 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1990 SILC_STATUS_ERR_BAD_CHANNEL);
1991 silc_free(channel_name);
1995 /* Get Client ID of the client who is joining to the channel */
1996 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1998 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1999 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2002 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2005 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2009 /* Get cipher name */
2010 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2012 /* See if the channel exists */
2013 channel = silc_idlist_find_channel_by_name(server->local_list,
2014 channel_name, NULL);
2016 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2017 /* If this is coming from client the Client ID in the command packet must
2018 be same as the client's ID. */
2019 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2020 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2021 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2022 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2023 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2029 /* Channel not found */
2031 /* If we are standalone server we don't have a router, we just create
2032 the channel by ourselves. */
2033 if (server->standalone) {
2034 channel = silc_server_create_new_channel(server, server->id, cipher,
2035 channel_name, TRUE);
2036 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2041 /* The channel does not exist on our server. If we are normal server
2042 we will send JOIN command to our router which will handle the
2043 joining procedure (either creates the channel if it doesn't exist
2044 or joins the client to it). */
2045 if (server->server_type == SILC_SERVER) {
2047 unsigned short old_ident;
2049 old_ident = silc_command_get_ident(cmd->payload);
2050 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2051 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2053 /* Send JOIN command to our router */
2054 silc_server_packet_send(server, (SilcSocketConnection)
2055 server->router->connection,
2056 SILC_PACKET_COMMAND, cmd->packet->flags,
2057 tmpbuf->data, tmpbuf->len, TRUE);
2059 /* Reprocess this packet after received reply from router */
2060 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2061 silc_command_get_ident(cmd->payload),
2062 silc_server_command_destructor,
2063 silc_server_command_join,
2064 silc_server_command_dup(cmd));
2065 cmd->pending = TRUE;
2069 /* We are router and the channel does not seem exist so we will check
2070 our global list as well for the channel. */
2071 channel = silc_idlist_find_channel_by_name(server->global_list,
2072 channel_name, NULL);
2074 /* Channel really does not exist, create it */
2075 channel = silc_server_create_new_channel(server, server->id, cipher,
2076 channel_name, TRUE);
2077 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2084 /* Channel not found */
2086 /* If the command came from router and/or we are normal server then
2087 something went wrong with the joining as the channel was not found.
2088 We can't do anything else but ignore this. */
2089 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2090 server->server_type == SILC_SERVER)
2093 /* We are router and the channel does not seem exist so we will check
2094 our global list as well for the channel. */
2095 channel = silc_idlist_find_channel_by_name(server->global_list,
2096 channel_name, NULL);
2098 /* Channel really does not exist, create it */
2099 channel = silc_server_create_new_channel(server, server->id, cipher,
2100 channel_name, TRUE);
2101 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2107 /* If the channel does not have global users and is also empty it means the
2108 channel was created globally (by our router) and the client will be the
2109 channel founder and operator. */
2110 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2111 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2112 created = TRUE; /* Created globally by our router */
2115 /* Join to the channel */
2116 silc_server_command_join_channel(server, cmd, channel, client_id,
2119 silc_free(client_id);
2122 silc_server_command_free(cmd);
2125 /* Server side of command MOTD. Sends server's current "message of the
2126 day" to the client. */
2128 SILC_SERVER_CMD_FUNC(motd)
2130 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2131 SilcServer server = cmd->server;
2135 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2137 /* XXX show currently only our motd */
2139 if (server->config && server->config->motd &&
2140 server->config->motd->motd_file) {
2143 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2148 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2154 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2159 silc_server_command_free(cmd);
2162 SILC_SERVER_CMD_FUNC(umode)
2166 /* Checks that client has rights to add or remove channel modes. If any
2167 of the checks fails FALSE is returned. */
2169 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2170 SilcChannelClientEntry client,
2173 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2174 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2176 /* Check whether has rights to change anything */
2177 if (!is_op && !is_fo)
2180 /* Check whether has rights to change everything */
2184 /* We know that client is channel operator, check that they are not
2185 changing anything that requires channel founder rights. Rest of the
2186 modes are available automatically for channel operator. */
2188 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2189 if (is_op && !is_fo)
2192 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2193 if (is_op && !is_fo)
2198 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2199 if (is_op && !is_fo)
2202 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2203 if (is_op && !is_fo)
2208 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2209 if (is_op && !is_fo)
2212 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2213 if (is_op && !is_fo)
2221 /* Server side command of CMODE. Changes channel mode */
2223 SILC_SERVER_CMD_FUNC(cmode)
2225 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2226 SilcServer server = cmd->server;
2227 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2228 SilcChannelID *channel_id;
2229 SilcChannelEntry channel;
2230 SilcChannelClientEntry chl;
2231 SilcBuffer packet, cidp;
2232 unsigned char *tmp, *tmp_id, *tmp_mask;
2233 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2235 SILC_LOG_DEBUG(("Start"));
2237 argc = silc_argument_get_arg_num(cmd->args);
2239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2240 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2245 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2249 /* Get Channel ID */
2250 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2253 SILC_STATUS_ERR_NO_CHANNEL_ID);
2256 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2259 SILC_STATUS_ERR_NO_CHANNEL_ID);
2263 /* Get the channel mode mask */
2264 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2267 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2270 SILC_GET32_MSB(mode_mask, tmp_mask);
2272 /* Get channel entry */
2273 channel = silc_idlist_find_channel_by_id(server->local_list,
2276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2277 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2281 /* Check whether this client is on the channel */
2282 if (!silc_server_client_on_channel(client, channel)) {
2283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2284 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2288 /* Get entry to the channel user list */
2289 silc_list_start(channel->user_list);
2290 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2291 if (chl->client == client)
2294 /* Check that client has rights to change any requested channel modes */
2295 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2296 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2297 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2302 * Check the modes. Modes that requires nothing special operation are
2306 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2307 /* Channel uses private keys to protect traffic. Client(s) has set the
2308 key locally they want to use, server does not know that key. */
2309 /* Nothing interesting to do here now */
2311 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2312 /* The mode is removed and we need to generate and distribute
2313 new channel key. Clients are not using private channel keys
2314 anymore after this. */
2316 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2319 /* Re-generate channel key */
2320 silc_server_create_channel_key(server, channel, 0);
2322 /* Encode channel key payload to be distributed on the channel */
2324 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2325 strlen(channel->channel_key->
2327 channel->channel_key->cipher->name,
2328 channel->key_len / 8, channel->key);
2330 /* If we are normal server then we will send it to our router. If we
2331 are router we will send it to all local servers that has clients on
2333 if (server->server_type == SILC_SERVER) {
2334 if (!server->standalone)
2335 silc_server_packet_send(server,
2336 cmd->server->router->connection,
2337 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2343 /* Send to locally connected clients on the channel */
2344 silc_server_packet_send_local_channel(server, channel,
2345 SILC_PACKET_CHANNEL_KEY, 0,
2346 packet->data, packet->len, FALSE);
2347 silc_buffer_free(packet);
2351 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2352 /* User limit is set on channel */
2353 unsigned int user_limit;
2355 /* Get user limit */
2356 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2358 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2360 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2364 SILC_GET32_MSB(user_limit, tmp);
2365 channel->mode_data.user_limit = user_limit;
2368 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2369 /* User limit mode is unset. Remove user limit */
2370 channel->mode_data.user_limit = 0;
2373 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2374 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2375 /* Passphrase has been set to channel */
2377 /* Get the passphrase */
2378 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2380 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2381 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2385 /* Save the passphrase */
2386 channel->mode_data.passphrase = strdup(tmp);
2389 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2390 /* Passphrase mode is unset. remove the passphrase */
2391 if (channel->mode_data.passphrase) {
2392 silc_free(channel->mode_data.passphrase);
2393 channel->mode_data.passphrase = NULL;
2398 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2399 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2400 /* Ban list is specified for channel */
2403 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2406 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2410 /* XXX check that channel founder is not banned */
2412 /* Save the ban list */
2413 channel->mode_data.ban_list = strdup(tmp);
2416 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2417 /* Ban mode is unset. Remove the entire ban list */
2418 if (channel->mode_data.ban_list) {
2419 silc_free(channel->mode_data.ban_list);
2420 channel->mode_data.ban_list = NULL;
2425 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2426 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2427 /* Invite list is specified for channel */
2429 /* Get invite list */
2430 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2433 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2437 /* Save the invite linst */
2438 channel->mode_data.invite_list = strdup(tmp);
2441 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2442 /* Invite list mode is unset. Remove the entire invite list */
2443 if (channel->mode_data.invite_list) {
2444 silc_free(channel->mode_data.invite_list);
2445 channel->mode_data.invite_list = NULL;
2450 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2451 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2452 /* Cipher to use protect the traffic */
2453 unsigned int key_len = 128;
2457 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2459 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2460 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2464 cp = strchr(tmp, ':');
2470 /* XXX Duplicated code, make own function for this!! */
2472 /* Delete old cipher and allocate the new one */
2473 silc_cipher_free(channel->channel_key);
2474 silc_cipher_alloc(tmp, &channel->channel_key);
2480 /* Re-generate channel key */
2481 silc_server_create_channel_key(server, channel, key_len);
2483 /* Encode channel key payload to be distributed on the channel */
2485 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2486 strlen(channel->channel_key->
2488 channel->channel_key->cipher->name,
2489 channel->key_len / 8, channel->key);
2491 /* If we are normal server then we will send it to our router. If we
2492 are router we will send it to all local servers that has clients on
2494 if (server->server_type == SILC_SERVER) {
2495 if (!server->standalone)
2496 silc_server_packet_send(server,
2497 cmd->server->router->connection,
2498 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2504 /* Send to locally connected clients on the channel */
2505 silc_server_packet_send_local_channel(server, channel,
2506 SILC_PACKET_CHANNEL_KEY, 0,
2507 packet->data, packet->len, FALSE);
2508 silc_buffer_free(packet);
2511 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2512 /* Cipher mode is unset. Remove the cipher and revert back to
2515 if (channel->mode_data.cipher) {
2516 silc_free(channel->mode_data.cipher);
2517 channel->mode_data.cipher = NULL;
2518 channel->mode_data.key_len = 0;
2521 /* Generate new cipher and key for the channel */
2523 /* XXX Duplicated code, make own function for this!! */
2525 /* Delete old cipher and allocate default one */
2526 silc_cipher_free(channel->channel_key);
2527 if (!channel->cipher)
2528 silc_cipher_alloc("twofish", &channel->channel_key);
2530 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2532 /* Re-generate channel key */
2533 silc_server_create_channel_key(server, channel, 0);
2535 /* Encode channel key payload to be distributed on the channel */
2537 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2538 strlen(channel->channel_key->
2540 channel->channel_key->cipher->name,
2541 channel->key_len / 8, channel->key);
2543 /* If we are normal server then we will send it to our router. If we
2544 are router we will send it to all local servers that has clients on
2546 if (server->server_type == SILC_SERVER) {
2547 if (!server->standalone)
2548 silc_server_packet_send(server,
2549 cmd->server->router->connection,
2550 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2556 /* Send to locally connected clients on the channel */
2557 silc_server_packet_send_local_channel(server, channel,
2558 SILC_PACKET_CHANNEL_KEY, 0,
2559 packet->data, packet->len, FALSE);
2560 silc_buffer_free(packet);
2564 /* Finally, set the mode */
2565 channel->mode = mode_mask;
2567 /* Send CMODE_CHANGE notify */
2568 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2569 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2570 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2571 cidp->data, cidp->len,
2575 /* Send command reply to sender */
2576 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2577 SILC_STATUS_OK, 0, 1,
2579 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2580 packet->data, packet->len, FALSE);
2582 silc_buffer_free(packet);
2583 silc_free(channel_id);
2586 silc_server_command_free(cmd);
2589 /* Server side of CUMODE command. Changes client's mode on a channel. */
2591 SILC_SERVER_CMD_FUNC(cumode)
2593 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2594 SilcServer server = cmd->server;
2595 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2596 SilcChannelID *channel_id;
2597 SilcClientID *client_id;
2598 SilcChannelEntry channel;
2599 SilcClientEntry target_client;
2600 SilcChannelClientEntry chl;
2601 SilcBuffer packet, idp;
2602 unsigned char *tmp_id, *tmp_mask;
2603 unsigned int target_mask, sender_mask, tmp_len;
2606 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2608 /* Get Channel ID */
2609 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2612 SILC_STATUS_ERR_NO_CHANNEL_ID);
2615 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2617 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2618 SILC_STATUS_ERR_NO_CHANNEL_ID);
2622 /* Get channel entry */
2623 channel = silc_idlist_find_channel_by_id(server->local_list,
2626 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2627 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2631 /* Check whether sender is on the channel */
2632 if (!silc_server_client_on_channel(client, channel)) {
2633 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2634 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2638 /* Check that client has rights to change other's rights */
2639 silc_list_start(channel->user_list);
2640 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2641 if (chl->client == client) {
2642 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2643 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2644 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2645 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2649 sender_mask = chl->mode;
2654 /* Get the target client's channel mode mask */
2655 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2657 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2658 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2661 SILC_GET32_MSB(target_mask, tmp_mask);
2663 /* Get target Client ID */
2664 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2666 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2667 SILC_STATUS_ERR_NO_CHANNEL_ID);
2670 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2673 SILC_STATUS_ERR_NO_CHANNEL_ID);
2677 /* Get target client's entry */
2678 target_client = silc_idlist_find_client_by_id(server->local_list,
2680 if (!target_client) {
2681 /* XXX If target client is not one of mine send to primary route */
2684 /* Check whether target client is on the channel */
2685 if (!silc_server_client_on_channel(target_client, channel)) {
2686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2687 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2691 /* Get entry to the channel user list */
2692 silc_list_start(channel->user_list);
2693 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2694 if (chl->client == target_client)
2701 /* If the target client is founder, no one else can change their mode
2703 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2704 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2705 SILC_STATUS_ERR_NOT_YOU);
2709 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2710 /* Cannot promote anyone to channel founder */
2711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2712 SILC_STATUS_ERR_NOT_YOU);
2715 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2716 if (target_client == client) {
2717 /* Remove channel founder rights from itself */
2718 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2721 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2722 SILC_STATUS_ERR_NOT_YOU);
2728 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2729 /* Promote to operator */
2730 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2731 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2735 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2736 /* Demote to normal user */
2737 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2742 /* Send notify to channel, notify only if mode was actually changed. */
2744 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2745 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2746 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2747 idp->data, idp->len,
2748 tmp_mask, 4, tmp_id, tmp_len);
2749 silc_buffer_free(idp);
2752 /* Send command reply to sender */
2753 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2754 SILC_STATUS_OK, 0, 2,
2756 3, tmp_id, tmp_len);
2757 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2758 packet->data, packet->len, FALSE);
2760 silc_buffer_free(packet);
2761 silc_free(channel_id);
2762 silc_free(client_id);
2765 silc_server_command_free(cmd);
2768 /* Server side of KICK command. Kicks client out of channel. */
2770 SILC_SERVER_CMD_FUNC(kick)
2774 SILC_SERVER_CMD_FUNC(restart)
2778 SILC_SERVER_CMD_FUNC(close)
2782 SILC_SERVER_CMD_FUNC(die)
2786 SILC_SERVER_CMD_FUNC(silcoper)
2790 /* Server side command of LEAVE. Removes client from a channel. */
2792 SILC_SERVER_CMD_FUNC(leave)
2794 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2795 SilcServer server = cmd->server;
2796 SilcSocketConnection sock = cmd->sock;
2797 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2799 SilcChannelEntry channel;
2801 unsigned int i, len;
2804 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2806 /* Get Channel ID */
2807 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2810 SILC_STATUS_ERR_NO_CHANNEL_ID);
2813 id = silc_id_payload_parse_id(tmp, len);
2815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2816 SILC_STATUS_ERR_NO_CHANNEL_ID);
2820 /* Get channel entry */
2821 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2824 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2828 /* Check whether this client is on the channel */
2829 if (!silc_server_client_on_channel(id_entry, channel)) {
2830 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2831 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2835 /* Notify routers that they should remove this client from their list
2836 of clients on the channel. */
2837 if (!server->standalone)
2838 silc_server_send_remove_channel_user(server,
2839 server->router->connection,
2840 server->server_type == SILC_ROUTER ?
2841 TRUE : FALSE, id_entry->id, id);
2843 /* Remove client from channel */
2844 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2849 /* If the channel does not exist anymore we won't send anything */
2853 /* Re-generate channel key */
2854 silc_server_create_channel_key(server, channel, 0);
2856 /* Encode channel key payload to be distributed on the channel */
2858 silc_channel_key_payload_encode(len, tmp,
2859 strlen(channel->channel_key->cipher->name),
2860 channel->channel_key->cipher->name,
2861 channel->key_len / 8, channel->key);
2863 /* If we are normal server then we will send it to our router. If we
2864 are router we will send it to all local servers that has clients on
2866 if (server->server_type == SILC_SERVER) {
2867 if (!server->standalone)
2868 silc_server_packet_send(server,
2869 cmd->server->router->connection,
2870 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2871 packet->len, FALSE);
2876 /* Send to locally connected clients on the channel */
2877 silc_server_packet_send_local_channel(server, channel,
2878 SILC_PACKET_CHANNEL_KEY, 0,
2879 packet->data, packet->len, FALSE);
2881 silc_buffer_free(packet);
2885 silc_server_command_free(cmd);
2888 /* Server side of command USERS. Resolves clients and their USERS currently
2889 joined on the requested channel. The list of Client ID's and their modes
2890 on the channel is sent back. */
2892 SILC_SERVER_CMD_FUNC(users)
2894 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2895 SilcServer server = cmd->server;
2896 SilcChannelEntry channel;
2897 SilcChannelClientEntry chl;
2900 unsigned char *channel_id;
2901 unsigned int channel_id_len;
2902 SilcBuffer client_id_list;
2903 SilcBuffer client_mode_list;
2905 unsigned char lc[4];
2906 unsigned int list_count = 0;
2907 unsigned short ident = silc_command_get_ident(cmd->payload);
2909 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
2911 /* Get Channel ID */
2912 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
2914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2915 SILC_STATUS_ERR_NO_CHANNEL_ID);
2918 id = silc_id_payload_parse_id(channel_id, channel_id_len);
2920 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2921 SILC_STATUS_ERR_NO_CHANNEL_ID);
2925 /* If we are server and we don't know about this channel we will send
2926 the command to our router. If we know about the channel then we also
2927 have the list of users already. */
2928 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2930 if (server->server_type == SILC_SERVER && !server->standalone &&
2934 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2935 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2937 /* Send USERS command */
2938 silc_server_packet_send(server, server->router->connection,
2939 SILC_PACKET_COMMAND, cmd->packet->flags,
2940 tmpbuf->data, tmpbuf->len, TRUE);
2942 /* Reprocess this packet after received reply */
2943 silc_server_command_pending(server, SILC_COMMAND_USERS,
2944 silc_command_get_ident(cmd->payload),
2945 silc_server_command_destructor,
2946 silc_server_command_users,
2947 silc_server_command_dup(cmd));
2948 cmd->pending = TRUE;
2949 silc_command_set_ident(cmd->payload, ident);
2951 silc_buffer_free(tmpbuf);
2956 /* We are router and we will check the global list as well. */
2957 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2959 /* Channel really does not exist */
2960 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2961 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2966 /* Assemble the lists now */
2968 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2969 silc_list_count(channel->user_list));
2970 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2972 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2973 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2975 silc_list_start(channel->user_list);
2976 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2978 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2979 silc_buffer_put(client_id_list, idp->data, idp->len);
2980 silc_buffer_pull(client_id_list, idp->len);
2981 silc_buffer_free(idp);
2983 /* Client's mode on channel */
2984 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2985 silc_buffer_pull(client_mode_list, 4);
2989 silc_buffer_push(client_id_list,
2990 client_id_list->data - client_id_list->head);
2991 silc_buffer_push(client_mode_list,
2992 client_mode_list->data - client_mode_list->head);
2995 SILC_PUT32_MSB(list_count, lc);
2998 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
2999 SILC_STATUS_OK, 0, 4,
3000 2, channel_id, channel_id_len,
3002 4, client_id_list->data,
3003 client_id_list->len,
3004 5, client_mode_list->data,
3005 client_mode_list->len);
3006 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3007 packet->data, packet->len, FALSE);
3009 silc_buffer_free(packet);
3010 silc_buffer_free(client_id_list);
3011 silc_buffer_free(client_mode_list);
3015 silc_server_command_free(cmd);