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 static void silc_server_command_free(SilcServerCommandContext cmd);
41 void silc_server_command_send_users(SilcServer server,
42 SilcSocketConnection sock,
43 SilcChannelEntry channel,
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
49 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
54 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(connect, CONNECT,
60 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
69 SILC_SERVER_CMD(restart, RESTART,
70 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
71 SILC_SERVER_CMD(close, CLOSE,
72 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
73 SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
74 SILC_SERVER_CMD(silcoper, SILCOPER,
75 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
77 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
82 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
84 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
86 SILC_LOG_DEBUG(("Start")); \
89 silc_server_command_send_status_reply(cmd, command, \
90 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
91 silc_server_command_free(cmd); \
95 silc_server_command_send_status_reply(cmd, command, \
96 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
97 silc_server_command_free(cmd); \
102 /* Returns TRUE if the connection is registered. Unregistered connections
103 usually cannot send commands hence the check. */
105 static int silc_server_is_registered(SilcServer server,
106 SilcSocketConnection sock,
107 SilcServerCommandContext cmd,
110 SilcIDListData idata = (SilcIDListData)sock->user_data;
111 if (idata->registered)
114 silc_server_command_send_status_reply(cmd, command,
115 SILC_STATUS_ERR_NOT_REGISTERED);
116 silc_server_command_free(cmd);
120 /* Processes received command packet. */
122 void silc_server_command_process(SilcServer server,
123 SilcSocketConnection sock,
124 SilcPacketContext *packet)
126 SilcServerCommandContext ctx;
127 SilcServerCommand *cmd;
130 /* XXX allow commands in but do not execute them more than once per
133 /* Check whether it is allowed for this connection to execute any
135 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
137 SilcClientEntry client = (SilcClientEntry)sock->user_data;
142 /* Allow only one command executed in 2 seconds. */
143 curtime = time(NULL);
144 if (client->last_command && (curtime - client->last_command) < 2)
147 /* Update access time */
148 client->last_command = curtime;
152 /* Allocate command context. This must be free'd by the
153 command routine receiving it. */
154 ctx = silc_calloc(1, sizeof(*ctx));
155 ctx->server = server;
157 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
159 /* Parse the command payload in the packet */
160 ctx->payload = silc_command_payload_parse(packet->buffer);
162 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
163 silc_buffer_free(packet->buffer);
164 silc_packet_context_free(packet);
168 ctx->args = silc_command_get_args(ctx->payload);
170 /* Execute command. If this fails the packet is dropped. */
171 for (cmd = silc_command_list; cmd->cb; cmd++)
172 if (cmd->cmd == silc_command_get(ctx->payload)) {
174 if (!(cmd->flags & SILC_CF_REG)) {
179 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
186 SILC_LOG_ERROR(("Unknown command, packet dropped"));
187 silc_server_command_free(ctx);
192 /* Add new pending command to be executed when reply to a command has been
193 received. The `reply_cmd' is the command that will call the `callback'
194 with `context' when reply has been received. If `ident' is non-zero
195 the `callback' will be executed when received reply with command
196 identifier `ident'. */
198 void silc_server_command_pending(SilcServer server,
199 SilcCommand reply_cmd,
200 unsigned short ident,
201 SilcCommandCb callback,
204 SilcServerCommandPending *reply;
206 reply = silc_calloc(1, sizeof(*reply));
207 reply->reply_cmd = reply_cmd;
208 reply->ident = ident;
209 reply->context = context;
210 reply->callback = callback;
211 silc_dlist_add(server->pending_commands, reply);
214 /* Deletes pending command by reply command type. */
216 void silc_server_command_pending_del(SilcServer server,
217 SilcCommand reply_cmd,
218 unsigned short ident)
220 SilcServerCommandPending *r;
222 silc_dlist_start(server->pending_commands);
223 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
224 if (r->reply_cmd == reply_cmd && r->ident == ident) {
225 silc_dlist_del(server->pending_commands, r);
231 /* Checks for pending commands and marks callbacks to be called from
232 the command reply function. Returns TRUE if there were pending command. */
234 int silc_server_command_pending_check(SilcServer server,
235 SilcServerCommandReplyContext ctx,
237 unsigned short ident)
239 SilcServerCommandPending *r;
241 silc_dlist_start(server->pending_commands);
242 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
243 if (r->reply_cmd == command && r->ident == ident) {
244 ctx->context = r->context;
245 ctx->callback = r->callback;
254 /* Free's the command context allocated before executing the command */
256 static void silc_server_command_free(SilcServerCommandContext cmd)
260 silc_command_free_payload(cmd->payload);
262 silc_packet_context_free(cmd->packet);
267 /* Sends simple status message as command reply packet */
270 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
272 SilcCommandStatus status)
276 SILC_LOG_DEBUG(("Sending command status %d", status));
278 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
279 silc_server_packet_send(cmd->server, cmd->sock,
280 SILC_PACKET_COMMAND_REPLY, 0,
281 buffer->data, buffer->len, FALSE);
282 silc_buffer_free(buffer);
285 /* Sends command status reply with one extra argument. The argument
286 type must be sent as argument. */
289 silc_server_command_send_status_data(SilcServerCommandContext cmd,
291 SilcCommandStatus status,
292 unsigned int arg_type,
294 unsigned int arg_len)
298 SILC_LOG_DEBUG(("Sending command status %d", status));
300 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
301 arg_type, arg, arg_len);
302 silc_server_packet_send(cmd->server, cmd->sock,
303 SILC_PACKET_COMMAND_REPLY, 0,
304 buffer->data, buffer->len, FALSE);
305 silc_buffer_free(buffer);
308 /******************************************************************************
312 ******************************************************************************/
315 silc_server_command_whois_parse(SilcServerCommandContext cmd,
316 SilcClientID ***client_id,
317 unsigned int *client_id_count,
325 unsigned int argc = silc_argument_get_arg_num(cmd->args);
328 /* If client ID is in the command it must be used instead of nickname */
329 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
331 /* No ID, get the nickname@server string and parse it. */
332 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
334 if (strchr(tmp, '@')) {
335 len = strcspn(tmp, "@");
336 *nickname = silc_calloc(len + 1, sizeof(char));
337 memcpy(*nickname, tmp, len);
338 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
339 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
341 *nickname = strdup(tmp);
344 silc_server_command_send_status_reply(cmd, command,
345 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
349 /* Command includes ID, we must use that. Also check whether the command
350 has more than one ID set - take them all. */
352 *client_id = silc_calloc(1, sizeof(**client_id));
353 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
354 if ((*client_id)[0] == NULL) {
355 silc_free(*client_id);
358 *client_id_count = 1;
360 /* Take all ID's from the command packet */
362 for (k = 1, i = 4; i < argc + 1; i++) {
363 tmp = silc_argument_get_arg_type(cmd->args, i, &len);
365 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
366 (*client_id_count + 1));
367 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
368 if ((*client_id)[k] == NULL) {
369 /* Cleanup all and fail */
370 for (i = 0; i < *client_id_count; i++)
371 silc_free((*client_id)[i]);
372 silc_free(*client_id);
375 (*client_id_count)++;
381 /* Command includes ID, use that */
384 /* Get the max count of reply messages allowed */
385 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
395 silc_server_command_whois_check(SilcServerCommandContext cmd,
396 SilcClientEntry *clients,
397 unsigned int clients_count)
399 SilcServer server = cmd->server;
401 SilcClientEntry entry;
403 for (i = 0; i < clients_count; i++) {
406 if (!entry->nickname || !entry->username) {
408 unsigned short old_ident;
413 old_ident = silc_command_get_ident(cmd->payload);
414 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
415 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
417 /* Send WHOIS command */
418 silc_server_packet_send(server, entry->router->connection,
419 SILC_PACKET_COMMAND, cmd->packet->flags,
420 tmpbuf->data, tmpbuf->len, TRUE);
422 /* Reprocess this packet after received reply */
423 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
424 silc_command_get_ident(cmd->payload),
425 silc_server_command_whois, (void *)cmd);
428 silc_command_set_ident(cmd->payload, old_ident);
430 silc_buffer_free(tmpbuf);
439 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
440 SilcClientEntry *clients,
441 unsigned int clients_count)
443 SilcServer server = cmd->server;
445 int i, count = 0, len;
446 SilcBuffer packet, idp;
447 SilcClientEntry entry;
448 SilcCommandStatus status;
449 unsigned short ident = silc_command_get_ident(cmd->payload);
451 status = SILC_STATUS_OK;
452 if (clients_count > 1)
453 status = SILC_STATUS_LIST_START;
455 for (i = 0; i < clients_count; i++) {
458 if (count && i - 1 == count)
461 if (clients_count > 2)
462 status = SILC_STATUS_LIST_ITEM;
464 if (clients_count > 1 && i == clients_count - 1)
465 status = SILC_STATUS_LIST_END;
467 /* Sanity check, however these should never fail. However, as
468 this sanity check has been added here they have failed. */
469 if (!entry->nickname || !entry->username)
472 /* Send WHOIS reply */
473 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
474 tmp = silc_argument_get_first_arg(cmd->args, NULL);
478 char nh[256], uh[256];
479 unsigned char idle[4];
480 SilcSocketConnection hsock;
482 memset(uh, 0, sizeof(uh));
483 memset(nh, 0, sizeof(nh));
485 strncat(nh, entry->nickname, strlen(entry->nickname));
486 if (!strchr(entry->nickname, '@')) {
488 len = entry->router ? strlen(entry->router->server_name) :
489 strlen(server->server_name);
490 strncat(nh, entry->router ? entry->router->server_name :
491 server->server_name, len);
494 strncat(uh, entry->username, strlen(entry->username));
495 if (!strchr(entry->username, '@')) {
497 hsock = (SilcSocketConnection)entry->connection;
498 len = strlen(hsock->hostname);
499 strncat(uh, hsock->hostname, len);
502 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
507 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
509 2, idp->data, idp->len,
513 strlen(entry->userinfo),
517 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
519 2, idp->data, idp->len,
525 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
526 0, packet->data, packet->len, FALSE);
528 silc_buffer_free(packet);
529 silc_buffer_free(idp);
534 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
536 SilcServer server = cmd->server;
537 char *nick = NULL, *server_name = NULL;
538 int count = 0, clients_count = 0;
539 SilcClientEntry *clients = NULL, entry;
540 SilcClientID **client_id = NULL;
541 unsigned int client_id_count = 0;
544 /* Protocol dictates that we must always send the received WHOIS request
545 to our router if we are normal server, so let's do it now unless we
546 are standalone. We will not send any replies to the client until we
547 have received reply from the router. */
548 if (server->server_type == SILC_SERVER &&
549 !cmd->pending && !server->standalone) {
551 unsigned short old_ident;
553 old_ident = silc_command_get_ident(cmd->payload);
554 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
555 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
557 /* Send WHOIS command to our router */
558 silc_server_packet_send(server, (SilcSocketConnection)
559 server->router->connection,
560 SILC_PACKET_COMMAND, cmd->packet->flags,
561 tmpbuf->data, tmpbuf->len, TRUE);
563 /* Reprocess this packet after received reply from router */
564 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
565 silc_command_get_ident(cmd->payload),
566 silc_server_command_whois, (void *)cmd);
569 silc_command_set_ident(cmd->payload, old_ident);
571 silc_buffer_free(tmpbuf);
576 /* We are ready to process the command request. Let's search for the
577 requested client and send reply to the requesting client. */
579 /* Parse the whois request */
580 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
581 &nick, &server_name, &count,
585 /* Get all clients matching that ID or nickname from local list */
586 if (client_id_count) {
587 /* Check all Client ID's received in the command packet */
588 for (i = 0; i < client_id_count; i++) {
589 entry = silc_idlist_find_client_by_id(server->local_list,
592 clients = silc_realloc(clients, sizeof(*clients) *
593 (clients_count + 1));
594 clients[clients_count++] = entry;
598 clients = silc_idlist_get_clients_by_nickname(server->local_list,
603 /* Check global list as well */
605 if (client_id_count) {
606 /* Check all Client ID's received in the command packet */
607 for (i = 0; i < client_id_count; i++) {
608 entry = silc_idlist_find_client_by_id(server->global_list,
611 clients = silc_realloc(clients, sizeof(*clients) *
612 (clients_count + 1));
613 clients[clients_count++] = entry;
617 clients = silc_idlist_get_clients_by_nickname(server->global_list,
624 /* Such client(s) really does not exist in the SILC network. */
625 if (!client_id_count) {
626 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
627 SILC_STATUS_ERR_NO_SUCH_NICK,
628 3, nick, strlen(nick));
630 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
631 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
632 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
633 2, idp->data, idp->len);
634 silc_buffer_free(idp);
639 /* Router always finds the client entry if it exists in the SILC network.
640 However, it might be incomplete entry and does not include all the
641 mandatory fields that WHOIS command reply requires. Check for these and
642 make query from the server who owns the client if some fields are
644 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
649 /* Send the command reply to the client */
650 silc_server_command_whois_send_reply(cmd, clients, clients_count);
653 if (client_id_count) {
654 for (i = 0; i < client_id_count; i++)
655 silc_free(client_id[i]);
656 silc_free(client_id);
663 silc_free(server_name);
669 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
671 SilcServer server = cmd->server;
672 char *nick = NULL, *server_name = NULL;
673 int count = 0, clients_count = 0;
674 SilcClientEntry *clients = NULL, entry;
675 SilcClientID **client_id = NULL;
676 unsigned int client_id_count = 0;
679 /* Parse the whois request */
680 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
681 &nick, &server_name, &count,
685 /* Process the command request. Let's search for the requested client and
686 send reply to the requesting server. */
688 if (client_id_count) {
689 /* Check all Client ID's received in the command packet */
690 for (i = 0; i < client_id_count; i++) {
691 entry = silc_idlist_find_client_by_id(server->local_list,
694 clients = silc_realloc(clients, sizeof(*clients) *
695 (clients_count + 1));
696 clients[clients_count++] = entry;
700 clients = silc_idlist_get_clients_by_nickname(server->local_list,
704 clients = silc_idlist_get_clients_by_hash(server->local_list,
705 nick, server->md5hash,
709 /* If we are router we will check our global list as well. */
710 if (!clients && server->server_type == SILC_ROUTER) {
711 if (client_id_count) {
712 /* Check all Client ID's received in the command packet */
713 for (i = 0; i < client_id_count; i++) {
714 entry = silc_idlist_find_client_by_id(server->global_list,
717 clients = silc_realloc(clients, sizeof(*clients) *
718 (clients_count + 1));
719 clients[clients_count++] = entry;
723 clients = silc_idlist_get_clients_by_nickname(server->global_list,
727 clients = silc_idlist_get_clients_by_hash(server->global_list,
728 nick, server->md5hash,
734 /* Such a client really does not exist in the SILC network. */
735 if (!client_id_count) {
736 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
737 SILC_STATUS_ERR_NO_SUCH_NICK,
738 3, nick, strlen(nick));
740 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
741 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
742 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
743 2, idp->data, idp->len);
744 silc_buffer_free(idp);
749 /* Router always finds the client entry if it exists in the SILC network.
750 However, it might be incomplete entry and does not include all the
751 mandatory fields that WHOIS command reply requires. Check for these and
752 make query from the server who owns the client if some fields are
754 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
759 /* Send the command reply to the client */
760 silc_server_command_whois_send_reply(cmd, clients, clients_count);
763 if (client_id_count) {
764 for (i = 0; i < client_id_count; i++)
765 silc_free(client_id[i]);
766 silc_free(client_id);
773 silc_free(server_name);
778 /* Server side of command WHOIS. Processes user's query and sends found
779 results as command replies back to the client. */
781 SILC_SERVER_CMD_FUNC(whois)
783 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
786 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
788 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
789 ret = silc_server_command_whois_from_client(cmd);
791 ret = silc_server_command_whois_from_server(cmd);
794 silc_server_command_free(cmd);
797 SILC_SERVER_CMD_FUNC(whowas)
801 /******************************************************************************
805 ******************************************************************************/
807 /* Checks that all mandatory fields are present. If not then send WHOIS
808 request to the server who owns the client. We use WHOIS because we want
809 to get as much information as possible at once. */
812 silc_server_command_identify_check(SilcServerCommandContext cmd,
813 SilcClientEntry *clients,
814 unsigned int clients_count)
816 SilcServer server = cmd->server;
818 SilcClientEntry entry;
820 for (i = 0; i < clients_count; i++) {
823 if (!entry->nickname) {
825 unsigned short old_ident;
830 old_ident = silc_command_get_ident(cmd->payload);
831 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
832 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
833 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
835 /* Send WHOIS request. We send WHOIS since we're doing the requesting
836 now anyway so make it a good one. */
837 silc_server_packet_send(server, entry->router->connection,
838 SILC_PACKET_COMMAND, cmd->packet->flags,
839 tmpbuf->data, tmpbuf->len, TRUE);
841 /* Reprocess this packet after received reply */
842 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
843 silc_command_get_ident(cmd->payload),
844 silc_server_command_identify, (void *)cmd);
847 /* Put old data back to the Command Payload we just changed */
848 silc_command_set_ident(cmd->payload, old_ident);
849 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
851 silc_buffer_free(tmpbuf);
860 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
861 SilcClientEntry *clients,
862 unsigned int clients_count)
864 SilcServer server = cmd->server;
866 int i, count = 0, len;
867 SilcBuffer packet, idp;
868 SilcClientEntry entry;
869 SilcCommandStatus status;
870 unsigned short ident = silc_command_get_ident(cmd->payload);
872 status = SILC_STATUS_OK;
873 if (clients_count > 1)
874 status = SILC_STATUS_LIST_START;
876 for (i = 0; i < clients_count; i++) {
879 if (count && i - 1 == count)
882 if (clients_count > 2)
883 status = SILC_STATUS_LIST_ITEM;
885 if (clients_count > 1 && i == clients_count - 1)
886 status = SILC_STATUS_LIST_END;
888 /* Send IDENTIFY reply */
889 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
890 tmp = silc_argument_get_first_arg(cmd->args, NULL);
894 char nh[256], uh[256];
895 SilcSocketConnection hsock;
897 memset(uh, 0, sizeof(uh));
898 memset(nh, 0, sizeof(nh));
900 strncat(nh, entry->nickname, strlen(entry->nickname));
901 if (!strchr(entry->nickname, '@')) {
903 len = entry->router ? strlen(entry->router->server_name) :
904 strlen(server->server_name);
905 strncat(nh, entry->router ? entry->router->server_name :
906 server->server_name, len);
909 if (!entry->username) {
910 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
911 SILC_STATUS_OK, ident, 2,
912 2, idp->data, idp->len,
915 strncat(uh, entry->username, strlen(entry->username));
916 if (!strchr(entry->username, '@')) {
918 hsock = (SilcSocketConnection)entry->connection;
919 len = strlen(hsock->hostname);
920 strncat(uh, hsock->hostname, len);
923 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
924 SILC_STATUS_OK, ident, 3,
925 2, idp->data, idp->len,
930 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
931 0, packet->data, packet->len, FALSE);
933 silc_buffer_free(packet);
934 silc_buffer_free(idp);
940 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
942 SilcServer server = cmd->server;
943 char *nick = NULL, *server_name = NULL;
944 int count = 0, clients_count = 0;
945 SilcClientEntry *clients = NULL, entry;
946 SilcClientID **client_id = NULL;
947 unsigned int client_id_count = 0;
950 /* Protocol dictates that we must always send the received IDENTIFY request
951 to our router if we are normal server, so let's do it now unless we
952 are standalone. We will not send any replies to the client until we
953 have received reply from the router. */
954 if (server->server_type == SILC_SERVER &&
955 !cmd->pending && !server->standalone) {
957 unsigned short old_ident;
959 old_ident = silc_command_get_ident(cmd->payload);
960 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
961 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
963 /* Send IDENTIFY command to our router */
964 silc_server_packet_send(server, (SilcSocketConnection)
965 server->router->connection,
966 SILC_PACKET_COMMAND, cmd->packet->flags,
967 tmpbuf->data, tmpbuf->len, TRUE);
969 /* Reprocess this packet after received reply from router */
970 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
971 silc_command_get_ident(cmd->payload),
972 silc_server_command_identify, (void *)cmd);
975 silc_command_set_ident(cmd->payload, old_ident);
977 silc_buffer_free(tmpbuf);
982 /* We are ready to process the command request. Let's search for the
983 requested client and send reply to the requesting client. */
985 /* Parse the IDENTIFY request */
986 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
987 &nick, &server_name, &count,
988 SILC_COMMAND_IDENTIFY))
991 /* Get all clients matching that ID or nickname from local list */
992 if (client_id_count) {
993 /* Check all Client ID's received in the command packet */
994 for (i = 0; i < client_id_count; i++) {
995 entry = silc_idlist_find_client_by_id(server->local_list,
998 clients = silc_realloc(clients, sizeof(*clients) *
999 (clients_count + 1));
1000 clients[clients_count++] = entry;
1004 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1009 /* Check global list as well */
1011 if (client_id_count) {
1012 /* Check all Client ID's received in the command packet */
1013 for (i = 0; i < client_id_count; i++) {
1014 entry = silc_idlist_find_client_by_id(server->global_list,
1015 client_id[i], NULL);
1017 clients = silc_realloc(clients, sizeof(*clients) *
1018 (clients_count + 1));
1019 clients[clients_count++] = entry;
1023 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1030 /* Such a client really does not exist in the SILC network. */
1031 if (!client_id_count) {
1032 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1033 SILC_STATUS_ERR_NO_SUCH_NICK,
1034 3, nick, strlen(nick));
1036 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1037 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1038 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1039 2, idp->data, idp->len);
1040 silc_buffer_free(idp);
1045 /* Check that all mandatory fields are present and request those data
1046 from the server who owns the client if necessary. */
1047 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1052 /* Send the command reply to the client */
1053 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1056 if (client_id_count) {
1057 for (i = 0; i < client_id_count; i++)
1058 silc_free(client_id[i]);
1059 silc_free(client_id);
1066 silc_free(server_name);
1072 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1074 SilcServer server = cmd->server;
1075 char *nick = NULL, *server_name = NULL;
1076 int count = 0, clients_count = 0;
1077 SilcClientEntry *clients = NULL, entry;
1078 SilcClientID **client_id = NULL;
1079 unsigned int client_id_count = 0;
1082 /* Parse the IDENTIFY request */
1083 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1084 &nick, &server_name, &count,
1085 SILC_COMMAND_IDENTIFY))
1088 /* Process the command request. Let's search for the requested client and
1089 send reply to the requesting server. */
1091 if (client_id_count) {
1092 /* Check all Client ID's received in the command packet */
1093 for (i = 0; i < client_id_count; i++) {
1094 entry = silc_idlist_find_client_by_id(server->local_list,
1095 client_id[i], NULL);
1097 clients = silc_realloc(clients, sizeof(*clients) *
1098 (clients_count + 1));
1099 clients[clients_count++] = entry;
1103 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1107 clients = silc_idlist_get_clients_by_hash(server->local_list,
1108 nick, server->md5hash,
1112 /* If we are router we will check our global list as well. */
1113 if (!clients && server->server_type == SILC_ROUTER) {
1114 if (client_id_count) {
1115 /* Check all Client ID's received in the command packet */
1116 for (i = 0; i < client_id_count; i++) {
1117 entry = silc_idlist_find_client_by_id(server->global_list,
1118 client_id[i], NULL);
1120 clients = silc_realloc(clients, sizeof(*clients) *
1121 (clients_count + 1));
1122 clients[clients_count++] = entry;
1126 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1130 clients = silc_idlist_get_clients_by_hash(server->global_list,
1131 nick, server->md5hash,
1137 /* Such a client really does not exist in the SILC network. */
1138 if (!client_id_count) {
1139 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1140 SILC_STATUS_ERR_NO_SUCH_NICK,
1141 3, nick, strlen(nick));
1143 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1144 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1145 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1146 2, idp->data, idp->len);
1147 silc_buffer_free(idp);
1152 /* Check that all mandatory fields are present and request those data
1153 from the server who owns the client if necessary. */
1154 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1159 /* Send the command reply */
1160 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1163 if (client_id_count) {
1164 for (i = 0; i < client_id_count; i++)
1165 silc_free(client_id[i]);
1166 silc_free(client_id);
1173 silc_free(server_name);
1178 SILC_SERVER_CMD_FUNC(identify)
1180 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1183 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1185 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1186 ret = silc_server_command_identify_from_client(cmd);
1188 ret = silc_server_command_identify_from_server(cmd);
1191 silc_server_command_free(cmd);
1194 /* Checks string for bad characters and returns TRUE if they are found. */
1196 static int silc_server_command_bad_chars(char *nick)
1198 if (strchr(nick, '\\')) return TRUE;
1199 if (strchr(nick, '\"')) return TRUE;
1200 if (strchr(nick, '´')) return TRUE;
1201 if (strchr(nick, '`')) return TRUE;
1202 if (strchr(nick, '\'')) return TRUE;
1203 if (strchr(nick, '*')) return TRUE;
1204 if (strchr(nick, '/')) return TRUE;
1205 if (strchr(nick, '@')) return TRUE;
1210 /* Server side of command NICK. Sets nickname for user. Setting
1211 nickname causes generation of a new client ID for the client. The
1212 new client ID is sent to the client after changing the nickname. */
1214 SILC_SERVER_CMD_FUNC(nick)
1216 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1217 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1218 SilcServer server = cmd->server;
1219 SilcBuffer packet, nidp, oidp;
1220 SilcClientID *new_id;
1223 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1225 /* Check nickname */
1226 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1227 if (silc_server_command_bad_chars(nick) == TRUE) {
1228 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1229 SILC_STATUS_ERR_BAD_NICKNAME);
1233 /* Create new Client ID */
1234 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1235 cmd->server->md5hash, nick,
1238 /* Send notify about nickname change to our router. We send the new
1239 ID and ask to replace it with the old one. If we are router the
1240 packet is broadcasted. */
1241 if (!server->standalone)
1242 silc_server_send_replace_id(server, server->router->connection,
1243 server->server_type == SILC_SERVER ?
1244 FALSE : TRUE, client->id,
1245 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1246 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1248 /* Remove old cache entry */
1249 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1252 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1256 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1257 silc_free(client->id);
1260 /* Save the nickname as this client is our local client */
1261 if (client->nickname)
1262 silc_free(client->nickname);
1264 client->nickname = strdup(nick);
1265 client->id = new_id;
1267 /* Update client cache */
1268 silc_idcache_add(server->local_list->clients, client->nickname,
1269 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1271 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1273 /* Send NICK_CHANGE notify */
1274 silc_server_send_notify_on_channels(server, client,
1275 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1276 oidp->data, oidp->len,
1277 nidp->data, nidp->len);
1279 /* Send the new Client ID as reply command back to client */
1280 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1281 SILC_STATUS_OK, 0, 1,
1282 2, nidp->data, nidp->len);
1283 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1284 0, packet->data, packet->len, FALSE);
1286 silc_buffer_free(packet);
1287 silc_buffer_free(nidp);
1288 silc_buffer_free(oidp);
1291 silc_server_command_free(cmd);
1294 SILC_SERVER_CMD_FUNC(list)
1298 /* Server side of TOPIC command. Sets topic for channel and/or returns
1299 current topic to client. */
1301 SILC_SERVER_CMD_FUNC(topic)
1303 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1304 SilcServer server = cmd->server;
1305 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1306 SilcChannelID *channel_id;
1307 SilcChannelEntry channel;
1308 SilcChannelClientEntry chl;
1309 SilcBuffer packet, idp;
1311 unsigned int argc, tmp_len;
1313 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1315 argc = silc_argument_get_arg_num(cmd->args);
1317 /* Get Channel ID */
1318 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1321 SILC_STATUS_ERR_NO_CHANNEL_ID);
1324 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1327 SILC_STATUS_ERR_NO_CHANNEL_ID);
1331 /* Check whether the channel exists */
1332 channel = silc_idlist_find_channel_by_id(server->local_list,
1335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1336 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1342 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1345 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1349 if (strlen(tmp) > 256) {
1350 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1351 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1355 /* See whether has rights to change topic */
1356 silc_list_start(channel->user_list);
1357 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1358 if (chl->client == client) {
1359 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1360 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1361 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1369 /* Set the topic for channel */
1371 silc_free(channel->topic);
1372 channel->topic = strdup(tmp);
1374 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1376 /* Send notify about topic change to all clients on the channel */
1377 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1378 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1379 idp->data, idp->len,
1380 channel->topic, strlen(channel->topic));
1381 silc_buffer_free(idp);
1384 /* Send the topic to client as reply packet */
1385 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1387 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1388 SILC_STATUS_OK, 0, 2,
1389 2, idp->data, idp->len,
1391 strlen(channel->topic));
1393 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1394 SILC_STATUS_OK, 0, 1,
1395 2, idp->data, idp->len);
1396 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1397 0, packet->data, packet->len, FALSE);
1399 silc_buffer_free(packet);
1400 silc_buffer_free(idp);
1401 silc_free(channel_id);
1404 silc_server_command_free(cmd);
1407 /* Server side of INVITE command. Invites some client to join some channel. */
1409 SILC_SERVER_CMD_FUNC(invite)
1411 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1412 SilcServer server = cmd->server;
1413 SilcSocketConnection sock = cmd->sock, dest_sock;
1414 SilcClientEntry sender, dest;
1415 SilcClientID *dest_id;
1416 SilcChannelEntry channel;
1417 SilcChannelID *channel_id;
1422 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1424 /* Get destination ID */
1425 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1428 SILC_STATUS_ERR_NO_CLIENT_ID);
1431 dest_id = silc_id_payload_parse_id(tmp, len);
1433 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1434 SILC_STATUS_ERR_NO_CLIENT_ID);
1438 /* Get Channel ID */
1439 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1442 SILC_STATUS_ERR_NO_CHANNEL_ID);
1445 channel_id = silc_id_payload_parse_id(tmp, len);
1447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1448 SILC_STATUS_ERR_NO_CHANNEL_ID);
1452 /* Check whether the channel exists */
1453 channel = silc_idlist_find_channel_by_id(server->local_list,
1456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1457 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1461 /* Check whether the sender of this command is on the channel. */
1462 sender = (SilcClientEntry)sock->user_data;
1463 if (!silc_server_client_on_channel(sender, channel)) {
1464 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1465 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1469 /* Check whether the channel is invite-only channel. If yes then the
1470 sender of this command must be at least channel operator. */
1471 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1472 SilcChannelClientEntry chl;
1474 silc_list_start(channel->user_list);
1475 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1476 if (chl->client == sender) {
1477 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1478 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1479 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1486 /* Find the connection data for the destination. If it is local we will
1487 send it directly otherwise we will send it to router for routing. */
1488 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1490 dest_sock = (SilcSocketConnection)dest->connection;
1492 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1494 /* Check whether the requested client is already on the channel. */
1495 /* XXX if we are normal server we don't know about global clients on
1496 the channel thus we must request it (USERS command), check from
1497 local cache as well. */
1498 if (silc_server_client_on_channel(dest, channel)) {
1499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1500 SILC_STATUS_ERR_USER_ON_CHANNEL);
1504 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1506 /* Send notify to the client that is invited to the channel */
1507 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1508 SILC_NOTIFY_TYPE_INVITE, 2,
1509 sidp->data, sidp->len, tmp, len);
1511 /* Send command reply */
1512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1515 silc_buffer_free(sidp);
1518 silc_server_command_free(cmd);
1521 /* Quits connection to client. This gets called if client won't
1522 close the connection even when it has issued QUIT command. */
1524 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1526 SilcServer server = (SilcServer)context;
1527 SilcSocketConnection sock = server->sockets[fd];
1529 /* Free all client specific data, such as client entry and entires
1530 on channels this client may be on. */
1531 silc_server_free_sock_user_data(server, sock);
1533 /* Close the connection on our side */
1534 silc_server_close_connection(server, sock);
1537 /* Quits SILC session. This is the normal way to disconnect client. */
1539 SILC_SERVER_CMD_FUNC(quit)
1541 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1542 SilcServer server = cmd->server;
1543 SilcSocketConnection sock = cmd->sock;
1545 SILC_LOG_DEBUG(("Start"));
1547 /* We quit the connection with little timeout */
1548 silc_task_register(server->timeout_queue, sock->sock,
1549 silc_server_command_quit_cb, server,
1550 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1552 silc_server_command_free(cmd);
1555 SILC_SERVER_CMD_FUNC(kill)
1559 /* Server side of command INFO. This sends information about us to
1560 the client. If client requested specific server we will send the
1561 command to that server. */
1563 SILC_SERVER_CMD_FUNC(info)
1565 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1566 SilcServer server = cmd->server;
1567 SilcBuffer packet, idp;
1568 char info_string[256], *dest_server;
1570 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1572 /* Get server name */
1573 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1575 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1576 SILC_STATUS_ERR_NO_SUCH_SERVER);
1580 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1581 /* Send our reply */
1582 memset(info_string, 0, sizeof(info_string));
1583 snprintf(info_string, sizeof(info_string),
1584 "location: %s server: %s admin: %s <%s>",
1585 server->config->admin_info->location,
1586 server->config->admin_info->server_type,
1587 server->config->admin_info->admin_name,
1588 server->config->admin_info->admin_email);
1590 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1592 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1593 SILC_STATUS_OK, 0, 2,
1594 2, idp->data, idp->len,
1596 strlen(info_string));
1597 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1598 packet->data, packet->len, FALSE);
1600 silc_buffer_free(packet);
1601 silc_buffer_free(idp);
1603 /* Send this command to the requested server */
1605 if (server->server_type == SILC_SERVER && !server->standalone) {
1609 if (server->server_type == SILC_ROUTER) {
1615 silc_server_command_free(cmd);
1618 SILC_SERVER_CMD_FUNC(connect)
1622 /* Server side of command PING. This just replies to the ping. */
1624 SILC_SERVER_CMD_FUNC(ping)
1626 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1627 SilcServer server = cmd->server;
1632 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1635 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1637 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1638 SILC_STATUS_ERR_NO_SERVER_ID);
1641 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1645 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1646 /* Send our reply */
1647 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1650 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1651 SILC_STATUS_ERR_NO_SUCH_SERVER);
1658 silc_server_command_free(cmd);
1661 SILC_SERVER_CMD_FUNC(oper)
1665 /* Assembles USERS command and executes it. This is called when client
1666 joins to a channel and we wan't to send USERS command reply to the
1669 void silc_server_command_send_users(SilcServer server,
1670 SilcSocketConnection sock,
1671 SilcChannelEntry channel,
1674 SilcServerCommandContext cmd;
1675 SilcBuffer buffer, idp;
1676 SilcPacketContext *packet = silc_packet_context_alloc();
1678 SILC_LOG_DEBUG(("Start"));
1680 /* Create USERS command packet and process it. */
1681 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1682 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1683 1, idp->data, idp->len);
1685 packet->buffer = silc_buffer_copy(buffer);
1686 packet->sock = sock;
1687 packet->type = SILC_PACKET_COMMAND;
1689 cmd = silc_calloc(1, sizeof(*cmd));
1690 cmd->payload = silc_command_payload_parse(buffer);
1691 if (!cmd->payload) {
1693 silc_buffer_free(buffer);
1694 silc_buffer_free(idp);
1695 silc_packet_context_free(packet);
1698 cmd->args = silc_command_get_args(cmd->payload);
1699 cmd->server = server;
1701 cmd->packet = silc_packet_context_dup(packet);
1702 cmd->pending = FALSE;
1705 /* If this function was called from pending command then instead of
1706 processing the command now, register a pending command callback which
1707 will process it after we've received the automatic USERS command
1709 silc_server_command_pending(server, SILC_COMMAND_USERS, 0,
1710 silc_server_command_users, (void *)cmd);
1711 cmd->pending = TRUE;
1712 silc_buffer_free(buffer);
1713 silc_buffer_free(idp);
1717 /* Process USERS command. */
1718 silc_server_command_users((void *)cmd);
1720 silc_buffer_free(buffer);
1721 silc_buffer_free(idp);
1722 silc_packet_context_free(packet);
1725 /* Internal routine to join channel. The channel sent to this function
1726 has been either created or resolved from ID lists. This joins the sent
1727 client to the channel. */
1729 static void silc_server_command_join_channel(SilcServer server,
1730 SilcServerCommandContext cmd,
1731 SilcChannelEntry channel,
1732 SilcClientID *client_id,
1736 SilcSocketConnection sock = cmd->sock;
1738 unsigned int tmp_len;
1739 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1740 SilcClientEntry client;
1741 SilcChannelClientEntry chl;
1742 SilcBuffer reply, chidp, clidp, keyp;
1743 unsigned short ident = silc_command_get_ident(cmd->payload);
1745 SILC_LOG_DEBUG(("Start"));
1750 /* Get passphrase */
1751 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1753 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1754 memcpy(passphrase, tmp, tmp_len);
1758 * Check channel modes
1761 /* Check invite list if channel is invite-only channel */
1762 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1763 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1764 /* Invite list is specified. Check whether client is invited in the
1765 list. If not, then check whether it has been invited otherwise. */
1768 /* XXX client must be invited to be able to join the channel */
1772 /* Check ban list if set */
1773 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1777 /* Check the channel passphrase if set. */
1778 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1779 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1780 strlen(channel->mode_data.passphrase))) {
1781 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1782 SILC_STATUS_ERR_BAD_PASSWORD);
1787 /* Check user count limit if set. */
1788 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1789 if (silc_list_count(channel->user_list) + 1 >
1790 channel->mode_data.user_limit) {
1791 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1792 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1798 * Client is allowed to join to the channel. Make it happen.
1801 /* Get the client entry */
1802 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1803 client = (SilcClientEntry)sock->user_data;
1805 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1808 /* XXX actually this is useless since router finds always cell's
1809 local clients from its local lists. */
1810 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1817 /* Check whether the client already is on the channel */
1818 if (silc_server_client_on_channel(client, channel)) {
1819 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1820 SILC_STATUS_ERR_USER_ON_CHANNEL);
1824 /* Generate new channel key as protocol dictates */
1825 if (!created || !channel->channel_key)
1826 silc_server_create_channel_key(server, channel, 0);
1828 /* Send the channel key. This is broadcasted to the channel but is not
1829 sent to the client who is joining to the channel. */
1830 silc_server_send_channel_key(server, NULL, channel,
1831 server->server_type == SILC_ROUTER ?
1832 FALSE : server->standalone);
1834 /* Join the client to the channel by adding it to channel's user list.
1835 Add also the channel to client entry's channels list for fast cross-
1837 chl = silc_calloc(1, sizeof(*chl));
1839 chl->client = client;
1840 chl->channel = channel;
1841 silc_list_add(channel->user_list, chl);
1842 silc_list_add(client->channels, chl);
1844 /* Encode Client ID Payload of the original client who wants to join */
1845 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1847 /* Encode command reply packet */
1848 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1849 SILC_PUT32_MSB(channel->mode, mode);
1850 SILC_PUT32_MSB(created, tmp2);
1851 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1852 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1853 SILC_ID_CHANNEL_LEN,
1854 channel->channel_key->cipher->name,
1855 channel->key_len / 8, channel->key);
1857 if (!channel->topic) {
1859 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1860 SILC_STATUS_OK, ident, 5,
1861 2, channel->channel_name,
1862 strlen(channel->channel_name),
1863 3, chidp->data, chidp->len,
1866 6, keyp->data, keyp->len);
1869 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1870 SILC_STATUS_OK, ident, 6,
1871 2, channel->channel_name,
1872 strlen(channel->channel_name),
1873 3, chidp->data, chidp->len,
1876 6, keyp->data, keyp->len,
1878 strlen(channel->topic));
1881 /* Send command reply */
1882 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1883 reply->data, reply->len, FALSE);
1885 if (!cmd->pending) {
1886 /* Send JOIN notify to locally connected clients on the channel */
1887 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1888 SILC_NOTIFY_TYPE_JOIN, 1,
1889 clidp->data, clidp->len);
1891 /* Send NEW_CHANNEL_USER packet to our primary router */
1892 if (!server->standalone)
1893 silc_server_send_new_channel_user(server, server->router->connection,
1894 server->server_type == SILC_SERVER ?
1896 channel->id, SILC_ID_CHANNEL_LEN,
1897 client->id, SILC_ID_CLIENT_LEN);
1900 /* Send USERS command reply to the joined channel so the user sees who
1901 is currently on the channel. */
1902 silc_server_command_send_users(server, sock, channel, cmd->pending);
1904 silc_buffer_free(reply);
1905 silc_buffer_free(clidp);
1906 silc_buffer_free(chidp);
1907 silc_buffer_free(keyp);
1911 silc_free(passphrase);
1914 /* Server side of command JOIN. Joins client into requested channel. If
1915 the channel does not exist it will be created. */
1917 SILC_SERVER_CMD_FUNC(join)
1919 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1920 SilcServer server = cmd->server;
1922 char *tmp, *channel_name = NULL, *cipher = NULL;
1923 SilcChannelEntry channel;
1924 unsigned int umode = 0;
1925 int created = FALSE;
1926 SilcClientID *client_id;
1928 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1930 /* Get channel name */
1931 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1934 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1939 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1940 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1941 SILC_STATUS_ERR_BAD_CHANNEL);
1942 silc_free(channel_name);
1946 /* Get Client ID of the client who is joining to the channel */
1947 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1950 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1953 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1956 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1960 /* Get cipher name */
1961 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
1963 /* See if the channel exists */
1964 channel = silc_idlist_find_channel_by_name(server->local_list,
1965 channel_name, NULL);
1967 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1968 /* If this is coming from client the Client ID in the command packet must
1969 be same as the client's ID. */
1970 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1971 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
1972 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
1973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1974 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1980 /* Channel not found */
1982 /* If we are standalone server we don't have a router, we just create
1983 the channel by ourselves. */
1984 if (server->standalone) {
1985 channel = silc_server_create_new_channel(server, server->id, cipher,
1987 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1992 /* The channel does not exist on our server. If we are normal server
1993 we will send JOIN command to our router which will handle the
1994 joining procedure (either creates the channel if it doesn't exist
1995 or joins the client to it). */
1996 if (server->server_type == SILC_SERVER) {
1998 unsigned short old_ident;
2000 old_ident = silc_command_get_ident(cmd->payload);
2001 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2002 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2004 /* Send JOIN command to our router */
2005 silc_server_packet_send(server, (SilcSocketConnection)
2006 server->router->connection,
2007 SILC_PACKET_COMMAND, cmd->packet->flags,
2008 tmpbuf->data, tmpbuf->len, TRUE);
2010 /* Reprocess this packet after received reply from router */
2011 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2012 silc_command_get_ident(cmd->payload),
2013 silc_server_command_join, context);
2014 cmd->pending = TRUE;
2018 /* We are router and the channel does not seem exist so we will check
2019 our global list as well for the channel. */
2020 channel = silc_idlist_find_channel_by_name(server->global_list,
2021 channel_name, NULL);
2023 /* Channel really does not exist, create it */
2024 channel = silc_server_create_new_channel(server, server->id, cipher,
2026 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2033 /* Channel not found */
2035 /* If the command came from router and/or we are normal server then
2036 something went wrong with the joining as the channel was not found.
2037 We can't do anything else but ignore this. */
2038 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2039 server->server_type == SILC_SERVER)
2042 /* We are router and the channel does not seem exist so we will check
2043 our global list as well for the channel. */
2044 channel = silc_idlist_find_channel_by_name(server->global_list,
2045 channel_name, NULL);
2047 /* Channel really does not exist, create it */
2048 channel = silc_server_create_new_channel(server, server->id, cipher,
2050 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2056 /* If the channel does not have global users and is also empty it means the
2057 channel was created globally (by our router) and the client will be the
2058 channel founder and operator. */
2059 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2060 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2061 created = TRUE; /* Created globally by our router */
2064 /* Join to the channel */
2065 silc_server_command_join_channel(server, cmd, channel, client_id,
2068 silc_free(client_id);
2071 silc_server_command_free(cmd);
2074 /* Server side of command MOTD. Sends server's current "message of the
2075 day" to the client. */
2077 SILC_SERVER_CMD_FUNC(motd)
2079 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2080 SilcServer server = cmd->server;
2084 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2086 /* XXX show currently only our motd */
2088 if (server->config && server->config->motd &&
2089 server->config->motd->motd_file) {
2092 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2097 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2103 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2108 silc_server_command_free(cmd);
2111 SILC_SERVER_CMD_FUNC(umode)
2115 /* Checks that client has rights to add or remove channel modes. If any
2116 of the checks fails FALSE is returned. */
2118 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2119 SilcChannelClientEntry client,
2122 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2123 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2125 /* Check whether has rights to change anything */
2126 if (!is_op && !is_fo)
2129 /* Check whether has rights to change everything */
2133 /* We know that client is channel operator, check that they are not
2134 changing anything that requires channel founder rights. Rest of the
2135 modes are available automatically for channel operator. */
2137 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2138 if (is_op && !is_fo)
2141 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2142 if (is_op && !is_fo)
2147 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2148 if (is_op && !is_fo)
2151 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2152 if (is_op && !is_fo)
2157 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2158 if (is_op && !is_fo)
2161 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2162 if (is_op && !is_fo)
2170 /* Server side command of CMODE. Changes channel mode */
2172 SILC_SERVER_CMD_FUNC(cmode)
2174 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2175 SilcServer server = cmd->server;
2176 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2177 SilcChannelID *channel_id;
2178 SilcChannelEntry channel;
2179 SilcChannelClientEntry chl;
2180 SilcBuffer packet, cidp;
2181 unsigned char *tmp, *tmp_id, *tmp_mask;
2182 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2184 SILC_LOG_DEBUG(("Start"));
2186 argc = silc_argument_get_arg_num(cmd->args);
2188 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2189 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2193 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2194 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2198 /* Get Channel ID */
2199 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2202 SILC_STATUS_ERR_NO_CHANNEL_ID);
2205 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2207 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2208 SILC_STATUS_ERR_NO_CHANNEL_ID);
2212 /* Get the channel mode mask */
2213 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2215 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2216 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2219 SILC_GET32_MSB(mode_mask, tmp_mask);
2221 /* Get channel entry */
2222 channel = silc_idlist_find_channel_by_id(server->local_list,
2225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2226 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2230 /* Check whether this client is on the channel */
2231 if (!silc_server_client_on_channel(client, channel)) {
2232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2233 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2237 /* Get entry to the channel user list */
2238 silc_list_start(channel->user_list);
2239 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2240 if (chl->client == client)
2243 /* Check that client has rights to change any requested channel modes */
2244 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2245 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2246 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2251 * Check the modes. Modes that requires nothing special operation are
2255 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2256 /* Channel uses private keys to protect traffic. Client(s) has set the
2257 key locally they want to use, server does not know that key. */
2258 /* Nothing interesting to do here now */
2260 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2261 /* The mode is removed and we need to generate and distribute
2262 new channel key. Clients are not using private channel keys
2263 anymore after this. */
2265 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2268 /* Re-generate channel key */
2269 silc_server_create_channel_key(server, channel, 0);
2271 /* Encode channel key payload to be distributed on the channel */
2273 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2274 strlen(channel->channel_key->
2276 channel->channel_key->cipher->name,
2277 channel->key_len / 8, channel->key);
2279 /* If we are normal server then we will send it to our router. If we
2280 are router we will send it to all local servers that has clients on
2282 if (server->server_type == SILC_SERVER) {
2283 if (!server->standalone)
2284 silc_server_packet_send(server,
2285 cmd->server->router->connection,
2286 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2292 /* Send to locally connected clients on the channel */
2293 silc_server_packet_send_local_channel(server, channel,
2294 SILC_PACKET_CHANNEL_KEY, 0,
2295 packet->data, packet->len, FALSE);
2296 silc_buffer_free(packet);
2300 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2301 /* User limit is set on channel */
2302 unsigned int user_limit;
2304 /* Get user limit */
2305 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2307 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2308 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2309 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2313 SILC_GET32_MSB(user_limit, tmp);
2314 channel->mode_data.user_limit = user_limit;
2317 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2318 /* User limit mode is unset. Remove user limit */
2319 channel->mode_data.user_limit = 0;
2322 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2323 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2324 /* Passphrase has been set to channel */
2326 /* Get the passphrase */
2327 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2330 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2334 /* Save the passphrase */
2335 channel->mode_data.passphrase = strdup(tmp);
2338 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2339 /* Passphrase mode is unset. remove the passphrase */
2340 if (channel->mode_data.passphrase) {
2341 silc_free(channel->mode_data.passphrase);
2342 channel->mode_data.passphrase = NULL;
2347 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2348 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2349 /* Ban list is specified for channel */
2352 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2354 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2355 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2359 /* XXX check that channel founder is not banned */
2361 /* Save the ban list */
2362 channel->mode_data.ban_list = strdup(tmp);
2365 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2366 /* Ban mode is unset. Remove the entire ban list */
2367 if (channel->mode_data.ban_list) {
2368 silc_free(channel->mode_data.ban_list);
2369 channel->mode_data.ban_list = NULL;
2374 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2375 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2376 /* Invite list is specified for channel */
2378 /* Get invite list */
2379 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2381 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2382 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2386 /* Save the invite linst */
2387 channel->mode_data.invite_list = strdup(tmp);
2390 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2391 /* Invite list mode is unset. Remove the entire invite list */
2392 if (channel->mode_data.invite_list) {
2393 silc_free(channel->mode_data.invite_list);
2394 channel->mode_data.invite_list = NULL;
2399 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2400 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2401 /* Cipher to use protect the traffic */
2402 unsigned int key_len = 128;
2406 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2409 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2413 cp = strchr(tmp, ':');
2419 /* XXX Duplicated code, make own function for this!! */
2421 /* Delete old cipher and allocate the new one */
2422 silc_cipher_free(channel->channel_key);
2423 silc_cipher_alloc(tmp, &channel->channel_key);
2429 /* Re-generate channel key */
2430 silc_server_create_channel_key(server, channel, key_len);
2432 /* Encode channel key payload to be distributed on the channel */
2434 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2435 strlen(channel->channel_key->
2437 channel->channel_key->cipher->name,
2438 channel->key_len / 8, channel->key);
2440 /* If we are normal server then we will send it to our router. If we
2441 are router we will send it to all local servers that has clients on
2443 if (server->server_type == SILC_SERVER) {
2444 if (!server->standalone)
2445 silc_server_packet_send(server,
2446 cmd->server->router->connection,
2447 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2453 /* Send to locally connected clients on the channel */
2454 silc_server_packet_send_local_channel(server, channel,
2455 SILC_PACKET_CHANNEL_KEY, 0,
2456 packet->data, packet->len, FALSE);
2457 silc_buffer_free(packet);
2460 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2461 /* Cipher mode is unset. Remove the cipher and revert back to
2464 if (channel->mode_data.cipher) {
2465 silc_free(channel->mode_data.cipher);
2466 channel->mode_data.cipher = NULL;
2467 channel->mode_data.key_len = 0;
2470 /* Generate new cipher and key for the channel */
2472 /* XXX Duplicated code, make own function for this!! */
2474 /* Delete old cipher and allocate default one */
2475 silc_cipher_free(channel->channel_key);
2476 if (!channel->cipher)
2477 silc_cipher_alloc("twofish", &channel->channel_key);
2479 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2481 /* Re-generate channel key */
2482 silc_server_create_channel_key(server, channel, 0);
2484 /* Encode channel key payload to be distributed on the channel */
2486 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2487 strlen(channel->channel_key->
2489 channel->channel_key->cipher->name,
2490 channel->key_len / 8, channel->key);
2492 /* If we are normal server then we will send it to our router. If we
2493 are router we will send it to all local servers that has clients on
2495 if (server->server_type == SILC_SERVER) {
2496 if (!server->standalone)
2497 silc_server_packet_send(server,
2498 cmd->server->router->connection,
2499 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2505 /* Send to locally connected clients on the channel */
2506 silc_server_packet_send_local_channel(server, channel,
2507 SILC_PACKET_CHANNEL_KEY, 0,
2508 packet->data, packet->len, FALSE);
2509 silc_buffer_free(packet);
2513 /* Finally, set the mode */
2514 channel->mode = mode_mask;
2516 /* Send CMODE_CHANGE notify */
2517 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2518 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2519 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2520 cidp->data, cidp->len,
2524 /* Send command reply to sender */
2525 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2526 SILC_STATUS_OK, 0, 1,
2528 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2529 packet->data, packet->len, FALSE);
2531 silc_buffer_free(packet);
2532 silc_free(channel_id);
2535 silc_server_command_free(cmd);
2538 /* Server side of CUMODE command. Changes client's mode on a channel. */
2540 SILC_SERVER_CMD_FUNC(cumode)
2542 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2543 SilcServer server = cmd->server;
2544 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2545 SilcChannelID *channel_id;
2546 SilcClientID *client_id;
2547 SilcChannelEntry channel;
2548 SilcClientEntry target_client;
2549 SilcChannelClientEntry chl;
2550 SilcBuffer packet, idp;
2551 unsigned char *tmp_id, *tmp_mask;
2552 unsigned int target_mask, sender_mask, tmp_len;
2555 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2557 /* Get Channel ID */
2558 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2561 SILC_STATUS_ERR_NO_CHANNEL_ID);
2564 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2567 SILC_STATUS_ERR_NO_CHANNEL_ID);
2571 /* Get channel entry */
2572 channel = silc_idlist_find_channel_by_id(server->local_list,
2575 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2576 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2580 /* Check whether sender is on the channel */
2581 if (!silc_server_client_on_channel(client, channel)) {
2582 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2583 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2587 /* Check that client has rights to change other's rights */
2588 silc_list_start(channel->user_list);
2589 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2590 if (chl->client == client) {
2591 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2592 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2593 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2594 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2598 sender_mask = chl->mode;
2603 /* Get the target client's channel mode mask */
2604 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2606 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2607 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2610 SILC_GET32_MSB(target_mask, tmp_mask);
2612 /* Get target Client ID */
2613 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2616 SILC_STATUS_ERR_NO_CHANNEL_ID);
2619 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2621 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2622 SILC_STATUS_ERR_NO_CHANNEL_ID);
2626 /* Get target client's entry */
2627 target_client = silc_idlist_find_client_by_id(server->local_list,
2629 if (!target_client) {
2630 /* XXX If target client is not one of mine send to primary route */
2633 /* Check whether target client is on the channel */
2634 if (!silc_server_client_on_channel(target_client, channel)) {
2635 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2636 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2640 /* Get entry to the channel user list */
2641 silc_list_start(channel->user_list);
2642 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2643 if (chl->client == target_client)
2650 /* If the target client is founder, no one else can change their mode
2652 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2653 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2654 SILC_STATUS_ERR_NOT_YOU);
2658 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2659 /* Cannot promote anyone to channel founder */
2660 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2661 SILC_STATUS_ERR_NOT_YOU);
2664 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2665 if (target_client == client) {
2666 /* Remove channel founder rights from itself */
2667 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2671 SILC_STATUS_ERR_NOT_YOU);
2677 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2678 /* Promote to operator */
2679 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2680 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2684 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2685 /* Demote to normal user */
2686 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2691 /* Send notify to channel, notify only if mode was actually changed. */
2693 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2694 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2695 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2696 idp->data, idp->len,
2697 tmp_mask, 4, tmp_id, tmp_len);
2698 silc_buffer_free(idp);
2701 /* Send command reply to sender */
2702 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2703 SILC_STATUS_OK, 0, 2,
2705 3, tmp_id, tmp_len);
2706 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2707 packet->data, packet->len, FALSE);
2709 silc_buffer_free(packet);
2710 silc_free(channel_id);
2711 silc_free(client_id);
2714 silc_server_command_free(cmd);
2717 /* Server side of KICK command. Kicks client out of channel. */
2719 SILC_SERVER_CMD_FUNC(kick)
2723 SILC_SERVER_CMD_FUNC(restart)
2727 SILC_SERVER_CMD_FUNC(close)
2731 SILC_SERVER_CMD_FUNC(die)
2735 SILC_SERVER_CMD_FUNC(silcoper)
2739 /* Server side command of LEAVE. Removes client from a channel. */
2741 SILC_SERVER_CMD_FUNC(leave)
2743 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2744 SilcServer server = cmd->server;
2745 SilcSocketConnection sock = cmd->sock;
2746 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2748 SilcChannelEntry channel;
2750 unsigned int i, len;
2753 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2755 /* Get Channel ID */
2756 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2758 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2759 SILC_STATUS_ERR_NO_CHANNEL_ID);
2762 id = silc_id_payload_parse_id(tmp, len);
2764 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2765 SILC_STATUS_ERR_NO_CHANNEL_ID);
2769 /* Get channel entry */
2770 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2773 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2777 /* Check whether this client is on the channel */
2778 if (!silc_server_client_on_channel(id_entry, channel)) {
2779 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2780 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2784 /* Notify routers that they should remove this client from their list
2785 of clients on the channel. */
2786 if (!server->standalone)
2787 silc_server_send_remove_channel_user(server,
2788 server->router->connection,
2789 server->server_type == SILC_ROUTER ?
2790 TRUE : FALSE, id_entry->id, id);
2792 /* Remove client from channel */
2793 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2798 /* If the channel does not exist anymore we won't send anything */
2802 /* Re-generate channel key */
2803 silc_server_create_channel_key(server, channel, 0);
2805 /* Encode channel key payload to be distributed on the channel */
2807 silc_channel_key_payload_encode(len, tmp,
2808 strlen(channel->channel_key->cipher->name),
2809 channel->channel_key->cipher->name,
2810 channel->key_len / 8, channel->key);
2812 /* If we are normal server then we will send it to our router. If we
2813 are router we will send it to all local servers that has clients on
2815 if (server->server_type == SILC_SERVER) {
2816 if (!server->standalone)
2817 silc_server_packet_send(server,
2818 cmd->server->router->connection,
2819 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2820 packet->len, FALSE);
2825 /* Send to locally connected clients on the channel */
2826 silc_server_packet_send_local_channel(server, channel,
2827 SILC_PACKET_CHANNEL_KEY, 0,
2828 packet->data, packet->len, FALSE);
2830 silc_buffer_free(packet);
2834 silc_server_command_free(cmd);
2837 /* Server side of command USERS. Resolves clients and their USERS currently
2838 joined on the requested channel. The list of Client ID's and their modes
2839 on the channel is sent back. */
2841 SILC_SERVER_CMD_FUNC(users)
2843 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2844 SilcServer server = cmd->server;
2845 SilcChannelEntry channel;
2846 SilcChannelClientEntry chl;
2849 unsigned char *channel_id;
2850 unsigned int channel_id_len;
2851 SilcBuffer client_id_list;
2852 SilcBuffer client_mode_list;
2854 unsigned char lc[4];
2855 unsigned int list_count = 0;
2856 unsigned short ident = silc_command_get_ident(cmd->payload);
2858 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
2860 /* Get Channel ID */
2861 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
2863 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2864 SILC_STATUS_ERR_NO_CHANNEL_ID);
2867 id = silc_id_payload_parse_id(channel_id, channel_id_len);
2869 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2870 SILC_STATUS_ERR_NO_CHANNEL_ID);
2874 /* If we are server and we don't know about this channel we will send
2875 the command to our router. If we know about the channel then we also
2876 have the list of users already. */
2877 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2879 if (server->server_type == SILC_SERVER && !server->standalone &&
2883 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2884 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2886 /* Send USERS command */
2887 silc_server_packet_send(server, server->router->connection,
2888 SILC_PACKET_COMMAND, cmd->packet->flags,
2889 tmpbuf->data, tmpbuf->len, TRUE);
2891 /* Reprocess this packet after received reply */
2892 silc_server_command_pending(server, SILC_COMMAND_USERS,
2893 silc_command_get_ident(cmd->payload),
2894 silc_server_command_users, (void *)cmd);
2895 cmd->pending = TRUE;
2896 silc_command_set_ident(cmd->payload, ident);
2898 silc_buffer_free(tmpbuf);
2903 /* We are router and we will check the global list as well. */
2904 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2906 /* Channel really does not exist */
2907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2908 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2913 /* Assemble the lists now */
2915 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2916 silc_list_count(channel->user_list));
2917 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2919 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2920 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2922 silc_list_start(channel->user_list);
2923 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2925 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2926 silc_buffer_put(client_id_list, idp->data, idp->len);
2927 silc_buffer_pull(client_id_list, idp->len);
2928 silc_buffer_free(idp);
2930 /* Client's mode on channel */
2931 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2932 silc_buffer_pull(client_mode_list, 4);
2936 silc_buffer_push(client_id_list,
2937 client_id_list->data - client_id_list->head);
2938 silc_buffer_push(client_mode_list,
2939 client_mode_list->data - client_mode_list->head);
2942 SILC_PUT32_MSB(list_count, lc);
2945 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
2946 SILC_STATUS_OK, 0, 4,
2947 2, channel_id, channel_id_len,
2949 4, client_id_list->data,
2950 client_id_list->len,
2951 5, client_mode_list->data,
2952 client_mode_list->len);
2953 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2954 packet->data, packet->len, FALSE);
2956 silc_buffer_free(packet);
2957 silc_buffer_free(client_id_list);
2958 silc_buffer_free(client_mode_list);
2962 silc_server_command_free(cmd);