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 || !entry->userinfo) {
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 /* Send WHOIS reply */
468 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
469 tmp = silc_argument_get_first_arg(cmd->args, NULL);
473 char nh[256], uh[256];
474 unsigned char idle[4];
475 SilcSocketConnection hsock;
477 memset(uh, 0, sizeof(uh));
478 memset(nh, 0, sizeof(nh));
480 strncat(nh, entry->nickname, strlen(entry->nickname));
481 if (!strchr(entry->nickname, '@')) {
483 len = entry->router ? strlen(entry->router->server_name) :
484 strlen(server->server_name);
485 strncat(nh, entry->router ? entry->router->server_name :
486 server->server_name, len);
489 strncat(uh, entry->username, strlen(entry->username));
490 if (!strchr(entry->username, '@')) {
492 hsock = (SilcSocketConnection)entry->connection;
493 len = strlen(hsock->hostname);
494 strncat(uh, hsock->hostname, len);
497 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
502 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
504 2, idp->data, idp->len,
508 strlen(entry->userinfo),
512 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
514 2, idp->data, idp->len,
520 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
521 0, packet->data, packet->len, FALSE);
523 silc_buffer_free(packet);
524 silc_buffer_free(idp);
529 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
531 SilcServer server = cmd->server;
532 char *nick = NULL, *server_name = NULL;
533 int count = 0, clients_count = 0;
534 SilcClientEntry *clients = NULL, entry;
535 SilcClientID **client_id = NULL;
536 unsigned int client_id_count = 0;
539 /* Protocol dictates that we must always send the received WHOIS request
540 to our router if we are normal server, so let's do it now unless we
541 are standalone. We will not send any replies to the client until we
542 have received reply from the router. */
543 if (server->server_type == SILC_SERVER &&
544 !cmd->pending && !server->standalone) {
546 unsigned short old_ident;
548 old_ident = silc_command_get_ident(cmd->payload);
549 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
550 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
552 /* Send WHOIS command to our router */
553 silc_server_packet_send(server, (SilcSocketConnection)
554 server->router->connection,
555 SILC_PACKET_COMMAND, cmd->packet->flags,
556 tmpbuf->data, tmpbuf->len, TRUE);
558 /* Reprocess this packet after received reply from router */
559 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
560 silc_command_get_ident(cmd->payload),
561 silc_server_command_whois, (void *)cmd);
564 silc_command_set_ident(cmd->payload, old_ident);
566 silc_buffer_free(tmpbuf);
571 /* We are ready to process the command request. Let's search for the
572 requested client and send reply to the requesting client. */
574 /* Parse the whois request */
575 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
576 &nick, &server_name, &count,
580 /* Get all clients matching that ID or nickname from local list */
581 if (client_id_count) {
582 /* Check all Client ID's received in the command packet */
583 for (i = 0; i < client_id_count; i++) {
584 entry = silc_idlist_find_client_by_id(server->local_list,
587 clients = silc_realloc(clients, sizeof(*clients) *
588 (clients_count + 1));
589 clients[clients_count++] = entry;
593 clients = silc_idlist_get_clients_by_nickname(server->local_list,
598 /* Check global list as well */
600 if (client_id_count) {
601 /* Check all Client ID's received in the command packet */
602 for (i = 0; i < client_id_count; i++) {
603 entry = silc_idlist_find_client_by_id(server->global_list,
606 clients = silc_realloc(clients, sizeof(*clients) *
607 (clients_count + 1));
608 clients[clients_count++] = entry;
612 clients = silc_idlist_get_clients_by_nickname(server->global_list,
619 /* Such client(s) really does not exist in the SILC network. */
620 if (!client_id_count) {
621 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
622 SILC_STATUS_ERR_NO_SUCH_NICK,
623 3, nick, strlen(nick));
625 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
626 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
627 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
628 2, idp->data, idp->len);
629 silc_buffer_free(idp);
634 /* Router always finds the client entry if it exists in the SILC network.
635 However, it might be incomplete entry and does not include all the
636 mandatory fields that WHOIS command reply requires. Check for these and
637 make query from the server who owns the client if some fields are
639 if (server->server_type == SILC_ROUTER &&
640 !silc_server_command_whois_check(cmd, clients, clients_count)) {
645 /* Send the command reply to the client */
646 silc_server_command_whois_send_reply(cmd, clients, clients_count);
649 if (client_id_count) {
650 for (i = 0; i < client_id_count; i++)
651 silc_free(client_id[i]);
652 silc_free(client_id);
659 silc_free(server_name);
665 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
667 SilcServer server = cmd->server;
668 char *nick = NULL, *server_name = NULL;
669 int count = 0, clients_count = 0;
670 SilcClientEntry *clients = NULL, entry;
671 SilcClientID **client_id = NULL;
672 unsigned int client_id_count = 0;
675 /* Parse the whois request */
676 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
677 &nick, &server_name, &count,
681 /* Process the command request. Let's search for the requested client and
682 send reply to the requesting server. */
684 if (client_id_count) {
685 /* Check all Client ID's received in the command packet */
686 for (i = 0; i < client_id_count; i++) {
687 entry = silc_idlist_find_client_by_id(server->local_list,
690 clients = silc_realloc(clients, sizeof(*clients) *
691 (clients_count + 1));
692 clients[clients_count++] = entry;
696 clients = silc_idlist_get_clients_by_nickname(server->local_list,
700 clients = silc_idlist_get_clients_by_hash(server->local_list,
701 nick, server->md5hash,
705 /* If we are router we will check our global list as well. */
706 if (!clients && server->server_type == SILC_ROUTER) {
707 if (client_id_count) {
708 /* Check all Client ID's received in the command packet */
709 for (i = 0; i < client_id_count; i++) {
710 entry = silc_idlist_find_client_by_id(server->global_list,
713 clients = silc_realloc(clients, sizeof(*clients) *
714 (clients_count + 1));
715 clients[clients_count++] = entry;
719 clients = silc_idlist_get_clients_by_nickname(server->global_list,
723 clients = silc_idlist_get_clients_by_hash(server->global_list,
724 nick, server->md5hash,
730 /* Such a client really does not exist in the SILC network. */
731 if (!client_id_count) {
732 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
733 SILC_STATUS_ERR_NO_SUCH_NICK,
734 3, nick, strlen(nick));
736 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
737 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
738 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
739 2, idp->data, idp->len);
740 silc_buffer_free(idp);
745 /* Router always finds the client entry if it exists in the SILC network.
746 However, it might be incomplete entry and does not include all the
747 mandatory fields that WHOIS command reply requires. Check for these and
748 make query from the server who owns the client if some fields are
750 if (server->server_type == SILC_ROUTER &&
751 !silc_server_command_whois_check(cmd, clients, clients_count)) {
756 /* Send the command reply to the client */
757 silc_server_command_whois_send_reply(cmd, clients, clients_count);
760 if (client_id_count) {
761 for (i = 0; i < client_id_count; i++)
762 silc_free(client_id[i]);
763 silc_free(client_id);
770 silc_free(server_name);
775 /* Server side of command WHOIS. Processes user's query and sends found
776 results as command replies back to the client. */
778 SILC_SERVER_CMD_FUNC(whois)
780 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
783 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
785 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
786 ret = silc_server_command_whois_from_client(cmd);
788 ret = silc_server_command_whois_from_server(cmd);
791 silc_server_command_free(cmd);
794 SILC_SERVER_CMD_FUNC(whowas)
798 /******************************************************************************
802 ******************************************************************************/
804 /* Checks that all mandatory fields are present. If not then send WHOIS
805 request to the server who owns the client. We use WHOIS because we want
806 to get as much information as possible at once. */
809 silc_server_command_identify_check(SilcServerCommandContext cmd,
810 SilcClientEntry *clients,
811 unsigned int clients_count)
813 SilcServer server = cmd->server;
815 SilcClientEntry entry;
817 for (i = 0; i < clients_count; i++) {
820 if (!entry->nickname) {
822 unsigned short old_ident;
827 old_ident = silc_command_get_ident(cmd->payload);
828 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
829 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
830 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
832 /* Send WHOIS request. We send WHOIS since we're doing the requesting
833 now anyway so make it a good one. */
834 silc_server_packet_send(server, entry->router->connection,
835 SILC_PACKET_COMMAND, cmd->packet->flags,
836 tmpbuf->data, tmpbuf->len, TRUE);
838 /* Reprocess this packet after received reply */
839 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
840 silc_command_get_ident(cmd->payload),
841 silc_server_command_identify, (void *)cmd);
844 /* Put old data back to the Command Payload we just changed */
845 silc_command_set_ident(cmd->payload, old_ident);
846 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
848 silc_buffer_free(tmpbuf);
857 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
858 SilcClientEntry *clients,
859 unsigned int clients_count)
861 SilcServer server = cmd->server;
863 int i, count = 0, len;
864 SilcBuffer packet, idp;
865 SilcClientEntry entry;
866 SilcCommandStatus status;
867 unsigned short ident = silc_command_get_ident(cmd->payload);
869 status = SILC_STATUS_OK;
870 if (clients_count > 1)
871 status = SILC_STATUS_LIST_START;
873 for (i = 0; i < clients_count; i++) {
876 if (count && i - 1 == count)
879 if (clients_count > 2)
880 status = SILC_STATUS_LIST_ITEM;
882 if (clients_count > 1 && i == clients_count - 1)
883 status = SILC_STATUS_LIST_END;
885 /* Send IDENTIFY reply */
886 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
887 tmp = silc_argument_get_first_arg(cmd->args, NULL);
891 char nh[256], uh[256];
892 SilcSocketConnection hsock;
894 memset(uh, 0, sizeof(uh));
895 memset(nh, 0, sizeof(nh));
897 strncat(nh, entry->nickname, strlen(entry->nickname));
898 if (!strchr(entry->nickname, '@')) {
900 len = entry->router ? strlen(entry->router->server_name) :
901 strlen(server->server_name);
902 strncat(nh, entry->router ? entry->router->server_name :
903 server->server_name, len);
906 if (!entry->username) {
907 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
908 SILC_STATUS_OK, ident, 2,
909 2, idp->data, idp->len,
912 strncat(uh, entry->username, strlen(entry->username));
913 if (!strchr(entry->username, '@')) {
915 hsock = (SilcSocketConnection)entry->connection;
916 len = strlen(hsock->hostname);
917 strncat(uh, hsock->hostname, len);
920 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
921 SILC_STATUS_OK, ident, 3,
922 2, idp->data, idp->len,
927 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
928 0, packet->data, packet->len, FALSE);
930 silc_buffer_free(packet);
931 silc_buffer_free(idp);
937 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
939 SilcServer server = cmd->server;
940 char *nick = NULL, *server_name = NULL;
941 int count = 0, clients_count = 0;
942 SilcClientEntry *clients = NULL, entry;
943 SilcClientID **client_id = NULL;
944 unsigned int client_id_count = 0;
947 /* Protocol dictates that we must always send the received IDENTIFY request
948 to our router if we are normal server, so let's do it now unless we
949 are standalone. We will not send any replies to the client until we
950 have received reply from the router. */
951 if (server->server_type == SILC_SERVER &&
952 !cmd->pending && !server->standalone) {
954 unsigned short old_ident;
956 old_ident = silc_command_get_ident(cmd->payload);
957 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
958 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
960 /* Send IDENTIFY command to our router */
961 silc_server_packet_send(server, (SilcSocketConnection)
962 server->router->connection,
963 SILC_PACKET_COMMAND, cmd->packet->flags,
964 tmpbuf->data, tmpbuf->len, TRUE);
966 /* Reprocess this packet after received reply from router */
967 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
968 silc_command_get_ident(cmd->payload),
969 silc_server_command_identify, (void *)cmd);
972 silc_command_set_ident(cmd->payload, old_ident);
974 silc_buffer_free(tmpbuf);
979 /* We are ready to process the command request. Let's search for the
980 requested client and send reply to the requesting client. */
982 /* Parse the IDENTIFY request */
983 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
984 &nick, &server_name, &count,
985 SILC_COMMAND_IDENTIFY))
988 /* Get all clients matching that ID or nickname from local list */
989 if (client_id_count) {
990 /* Check all Client ID's received in the command packet */
991 for (i = 0; i < client_id_count; i++) {
992 entry = silc_idlist_find_client_by_id(server->local_list,
995 clients = silc_realloc(clients, sizeof(*clients) *
996 (clients_count + 1));
997 clients[clients_count++] = entry;
1001 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1006 /* Check global list as well */
1008 if (client_id_count) {
1009 /* Check all Client ID's received in the command packet */
1010 for (i = 0; i < client_id_count; i++) {
1011 entry = silc_idlist_find_client_by_id(server->global_list,
1012 client_id[i], NULL);
1014 clients = silc_realloc(clients, sizeof(*clients) *
1015 (clients_count + 1));
1016 clients[clients_count++] = entry;
1020 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1027 /* Such a client really does not exist in the SILC network. */
1028 if (!client_id_count) {
1029 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1030 SILC_STATUS_ERR_NO_SUCH_NICK,
1031 3, nick, strlen(nick));
1033 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1034 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1035 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1036 2, idp->data, idp->len);
1037 silc_buffer_free(idp);
1042 /* Check that all mandatory fields are present and request those data
1043 from the server who owns the client if necessary. */
1044 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1045 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1050 /* Send the command reply to the client */
1051 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1054 if (client_id_count) {
1055 for (i = 0; i < client_id_count; i++)
1056 silc_free(client_id[i]);
1057 silc_free(client_id);
1064 silc_free(server_name);
1070 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1072 SilcServer server = cmd->server;
1073 char *nick = NULL, *server_name = NULL;
1074 int count = 0, clients_count = 0;
1075 SilcClientEntry *clients = NULL, entry;
1076 SilcClientID **client_id = NULL;
1077 unsigned int client_id_count = 0;
1080 /* Parse the IDENTIFY request */
1081 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1082 &nick, &server_name, &count,
1083 SILC_COMMAND_IDENTIFY))
1086 /* Process the command request. Let's search for the requested client and
1087 send reply to the requesting server. */
1089 if (client_id_count) {
1090 /* Check all Client ID's received in the command packet */
1091 for (i = 0; i < client_id_count; i++) {
1092 entry = silc_idlist_find_client_by_id(server->local_list,
1093 client_id[i], NULL);
1095 clients = silc_realloc(clients, sizeof(*clients) *
1096 (clients_count + 1));
1097 clients[clients_count++] = entry;
1101 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1105 clients = silc_idlist_get_clients_by_hash(server->local_list,
1106 nick, server->md5hash,
1110 /* If we are router we will check our global list as well. */
1111 if (!clients && server->server_type == SILC_ROUTER) {
1112 if (client_id_count) {
1113 /* Check all Client ID's received in the command packet */
1114 for (i = 0; i < client_id_count; i++) {
1115 entry = silc_idlist_find_client_by_id(server->global_list,
1116 client_id[i], NULL);
1118 clients = silc_realloc(clients, sizeof(*clients) *
1119 (clients_count + 1));
1120 clients[clients_count++] = entry;
1124 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1128 clients = silc_idlist_get_clients_by_hash(server->global_list,
1129 nick, server->md5hash,
1135 /* Such a client really does not exist in the SILC network. */
1136 if (!client_id_count) {
1137 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1138 SILC_STATUS_ERR_NO_SUCH_NICK,
1139 3, nick, strlen(nick));
1141 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1142 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1143 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1144 2, idp->data, idp->len);
1145 silc_buffer_free(idp);
1150 /* Check that all mandatory fields are present and request those data
1151 from the server who owns the client if necessary. */
1152 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1153 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1158 /* Send the command reply */
1159 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1162 if (client_id_count) {
1163 for (i = 0; i < client_id_count; i++)
1164 silc_free(client_id[i]);
1165 silc_free(client_id);
1172 silc_free(server_name);
1177 SILC_SERVER_CMD_FUNC(identify)
1179 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1182 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1184 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1185 ret = silc_server_command_identify_from_client(cmd);
1187 ret = silc_server_command_identify_from_server(cmd);
1190 silc_server_command_free(cmd);
1193 /* Checks string for bad characters and returns TRUE if they are found. */
1195 static int silc_server_command_bad_chars(char *nick)
1197 if (strchr(nick, '\\')) return TRUE;
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;
1209 /* Server side of command NICK. Sets nickname for user. Setting
1210 nickname causes generation of a new client ID for the client. The
1211 new client ID is sent to the client after changing the nickname. */
1213 SILC_SERVER_CMD_FUNC(nick)
1215 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1216 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1217 SilcServer server = cmd->server;
1218 SilcBuffer packet, nidp, oidp;
1219 SilcClientID *new_id;
1222 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1224 /* Check nickname */
1225 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1226 if (silc_server_command_bad_chars(nick) == TRUE) {
1227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1228 SILC_STATUS_ERR_BAD_NICKNAME);
1232 /* Create new Client ID */
1233 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1234 cmd->server->md5hash, nick,
1237 /* Send notify about nickname change to our router. We send the new
1238 ID and ask to replace it with the old one. If we are router the
1239 packet is broadcasted. */
1240 if (!server->standalone)
1241 silc_server_send_replace_id(server, server->router->connection,
1242 server->server_type == SILC_SERVER ?
1243 FALSE : TRUE, client->id,
1244 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1245 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1247 /* Remove old cache entry */
1248 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1251 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1255 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1256 silc_free(client->id);
1259 /* Save the nickname as this client is our local client */
1260 if (client->nickname)
1261 silc_free(client->nickname);
1263 client->nickname = strdup(nick);
1264 client->id = new_id;
1266 /* Update client cache */
1267 silc_idcache_add(server->local_list->clients, client->nickname,
1268 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1270 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1272 /* Send NICK_CHANGE notify */
1273 silc_server_send_notify_on_channels(server, client,
1274 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1275 oidp->data, oidp->len,
1276 nidp->data, nidp->len);
1278 /* Send the new Client ID as reply command back to client */
1279 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1280 SILC_STATUS_OK, 0, 1,
1281 2, nidp->data, nidp->len);
1282 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1283 0, packet->data, packet->len, FALSE);
1285 silc_buffer_free(packet);
1286 silc_buffer_free(nidp);
1287 silc_buffer_free(oidp);
1290 silc_server_command_free(cmd);
1293 SILC_SERVER_CMD_FUNC(list)
1297 /* Server side of TOPIC command. Sets topic for channel and/or returns
1298 current topic to client. */
1300 SILC_SERVER_CMD_FUNC(topic)
1302 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1303 SilcServer server = cmd->server;
1304 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1305 SilcChannelID *channel_id;
1306 SilcChannelEntry channel;
1307 SilcChannelClientEntry chl;
1308 SilcBuffer packet, idp;
1310 unsigned int argc, tmp_len;
1312 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1314 argc = silc_argument_get_arg_num(cmd->args);
1316 /* Get Channel ID */
1317 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1320 SILC_STATUS_ERR_NO_CHANNEL_ID);
1323 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1326 SILC_STATUS_ERR_NO_CHANNEL_ID);
1330 /* Check whether the channel exists */
1331 channel = silc_idlist_find_channel_by_id(server->local_list,
1334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1335 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1341 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1344 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1348 if (strlen(tmp) > 256) {
1349 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1350 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1354 /* See whether has rights to change topic */
1355 silc_list_start(channel->user_list);
1356 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1357 if (chl->client == client) {
1358 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1360 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1368 /* Set the topic for channel */
1370 silc_free(channel->topic);
1371 channel->topic = strdup(tmp);
1373 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1375 /* Send notify about topic change to all clients on the channel */
1376 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1377 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1378 idp->data, idp->len,
1379 channel->topic, strlen(channel->topic));
1380 silc_buffer_free(idp);
1383 /* Send the topic to client as reply packet */
1384 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1386 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1387 SILC_STATUS_OK, 0, 2,
1388 2, idp->data, idp->len,
1390 strlen(channel->topic));
1392 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1393 SILC_STATUS_OK, 0, 1,
1394 2, idp->data, idp->len);
1395 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1396 0, packet->data, packet->len, FALSE);
1398 silc_buffer_free(packet);
1399 silc_buffer_free(idp);
1400 silc_free(channel_id);
1403 silc_server_command_free(cmd);
1406 /* Server side of INVITE command. Invites some client to join some channel. */
1408 SILC_SERVER_CMD_FUNC(invite)
1410 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1411 SilcServer server = cmd->server;
1412 SilcSocketConnection sock = cmd->sock, dest_sock;
1413 SilcClientEntry sender, dest;
1414 SilcClientID *dest_id;
1415 SilcChannelEntry channel;
1416 SilcChannelID *channel_id;
1421 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1423 /* Get destination ID */
1424 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1427 SILC_STATUS_ERR_NO_CLIENT_ID);
1430 dest_id = silc_id_payload_parse_id(tmp, len);
1432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1433 SILC_STATUS_ERR_NO_CLIENT_ID);
1437 /* Get Channel ID */
1438 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1441 SILC_STATUS_ERR_NO_CHANNEL_ID);
1444 channel_id = silc_id_payload_parse_id(tmp, len);
1446 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1447 SILC_STATUS_ERR_NO_CHANNEL_ID);
1451 /* Check whether the channel exists */
1452 channel = silc_idlist_find_channel_by_id(server->local_list,
1455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1456 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1460 /* Check whether the sender of this command is on the channel. */
1461 sender = (SilcClientEntry)sock->user_data;
1462 if (!silc_server_client_on_channel(sender, channel)) {
1463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1464 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1468 /* Check whether the channel is invite-only channel. If yes then the
1469 sender of this command must be at least channel operator. */
1470 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1471 SilcChannelClientEntry chl;
1473 silc_list_start(channel->user_list);
1474 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1475 if (chl->client == sender) {
1476 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1477 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1478 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1485 /* Find the connection data for the destination. If it is local we will
1486 send it directly otherwise we will send it to router for routing. */
1487 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1489 dest_sock = (SilcSocketConnection)dest->connection;
1491 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1493 /* Check whether the requested client is already on the channel. */
1494 /* XXX if we are normal server we don't know about global clients on
1495 the channel thus we must request it (USERS command), check from
1496 local cache as well. */
1497 if (silc_server_client_on_channel(dest, channel)) {
1498 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1499 SILC_STATUS_ERR_USER_ON_CHANNEL);
1503 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1505 /* Send notify to the client that is invited to the channel */
1506 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1507 SILC_NOTIFY_TYPE_INVITE, 2,
1508 sidp->data, sidp->len, tmp, len);
1510 /* Send command reply */
1511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1514 silc_buffer_free(sidp);
1517 silc_server_command_free(cmd);
1520 /* Quits connection to client. This gets called if client won't
1521 close the connection even when it has issued QUIT command. */
1523 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1525 SilcServer server = (SilcServer)context;
1526 SilcSocketConnection sock = server->sockets[fd];
1528 /* Free all client specific data, such as client entry and entires
1529 on channels this client may be on. */
1530 silc_server_free_sock_user_data(server, sock);
1532 /* Close the connection on our side */
1533 silc_server_close_connection(server, sock);
1536 /* Quits SILC session. This is the normal way to disconnect client. */
1538 SILC_SERVER_CMD_FUNC(quit)
1540 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1541 SilcServer server = cmd->server;
1542 SilcSocketConnection sock = cmd->sock;
1544 SILC_LOG_DEBUG(("Start"));
1546 /* We quit the connection with little timeout */
1547 silc_task_register(server->timeout_queue, sock->sock,
1548 silc_server_command_quit_cb, server,
1549 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1551 silc_server_command_free(cmd);
1554 SILC_SERVER_CMD_FUNC(kill)
1558 /* Server side of command INFO. This sends information about us to
1559 the client. If client requested specific server we will send the
1560 command to that server. */
1562 SILC_SERVER_CMD_FUNC(info)
1564 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1565 SilcServer server = cmd->server;
1566 SilcBuffer packet, idp;
1567 char info_string[256], *dest_server;
1569 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1571 /* Get server name */
1572 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1574 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1575 SILC_STATUS_ERR_NO_SUCH_SERVER);
1579 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1580 /* Send our reply */
1581 memset(info_string, 0, sizeof(info_string));
1582 snprintf(info_string, sizeof(info_string),
1583 "location: %s server: %s admin: %s <%s>",
1584 server->config->admin_info->location,
1585 server->config->admin_info->server_type,
1586 server->config->admin_info->admin_name,
1587 server->config->admin_info->admin_email);
1589 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1591 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1592 SILC_STATUS_OK, 0, 2,
1593 2, idp->data, idp->len,
1595 strlen(info_string));
1596 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1597 packet->data, packet->len, FALSE);
1599 silc_buffer_free(packet);
1600 silc_buffer_free(idp);
1602 /* Send this command to the requested server */
1604 if (server->server_type == SILC_SERVER && !server->standalone) {
1608 if (server->server_type == SILC_ROUTER) {
1614 silc_server_command_free(cmd);
1617 SILC_SERVER_CMD_FUNC(connect)
1621 /* Server side of command PING. This just replies to the ping. */
1623 SILC_SERVER_CMD_FUNC(ping)
1625 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1626 SilcServer server = cmd->server;
1631 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1634 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1637 SILC_STATUS_ERR_NO_SERVER_ID);
1640 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1644 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1645 /* Send our reply */
1646 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1649 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1650 SILC_STATUS_ERR_NO_SUCH_SERVER);
1657 silc_server_command_free(cmd);
1660 SILC_SERVER_CMD_FUNC(oper)
1664 /* Assembles USERS command and executes it. This is called when client
1665 joins to a channel and we wan't to send USERS command reply to the
1668 void silc_server_command_send_users(SilcServer server,
1669 SilcSocketConnection sock,
1670 SilcChannelEntry channel,
1673 SilcServerCommandContext cmd;
1674 SilcBuffer buffer, idp;
1675 SilcPacketContext *packet = silc_packet_context_alloc();
1677 SILC_LOG_DEBUG(("Start"));
1679 /* Create USERS command packet and process it. */
1680 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1681 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1682 1, idp->data, idp->len);
1684 packet->buffer = silc_buffer_copy(buffer);
1685 packet->sock = sock;
1686 packet->type = SILC_PACKET_COMMAND;
1688 cmd = silc_calloc(1, sizeof(*cmd));
1689 cmd->payload = silc_command_payload_parse(buffer);
1690 if (!cmd->payload) {
1692 silc_buffer_free(buffer);
1693 silc_buffer_free(idp);
1694 silc_packet_context_free(packet);
1697 cmd->args = silc_command_get_args(cmd->payload);
1698 cmd->server = server;
1700 cmd->packet = silc_packet_context_dup(packet);
1701 cmd->pending = FALSE;
1704 /* If this function was called from pending command then instead of
1705 processing the command now, register a pending command callback which
1706 will process it after we've received the automatic USERS command
1708 silc_server_command_pending(server, SILC_COMMAND_USERS, 0,
1709 silc_server_command_users, (void *)cmd);
1710 cmd->pending = TRUE;
1711 silc_buffer_free(buffer);
1712 silc_buffer_free(idp);
1716 /* Process USERS command. */
1717 silc_server_command_users((void *)cmd);
1719 silc_buffer_free(buffer);
1720 silc_buffer_free(idp);
1721 silc_packet_context_free(packet);
1724 /* Internal routine to join channel. The channel sent to this function
1725 has been either created or resolved from ID lists. This joins the sent
1726 client to the channel. */
1728 static void silc_server_command_join_channel(SilcServer server,
1729 SilcServerCommandContext cmd,
1730 SilcChannelEntry channel,
1731 SilcClientID *client_id,
1735 SilcSocketConnection sock = cmd->sock;
1737 unsigned int tmp_len;
1738 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1739 SilcClientEntry client;
1740 SilcChannelClientEntry chl;
1741 SilcBuffer reply, chidp, clidp, keyp;
1742 unsigned short ident = silc_command_get_ident(cmd->payload);
1744 SILC_LOG_DEBUG(("Start"));
1749 /* Get passphrase */
1750 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1752 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1753 memcpy(passphrase, tmp, tmp_len);
1757 * Check channel modes
1760 /* Check invite list if channel is invite-only channel */
1761 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1762 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1763 /* Invite list is specified. Check whether client is invited in the
1764 list. If not, then check whether it has been invited otherwise. */
1767 /* XXX client must be invited to be able to join the channel */
1771 /* Check ban list if set */
1772 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1776 /* Check the channel passphrase if set. */
1777 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1778 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1779 strlen(channel->mode_data.passphrase))) {
1780 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1781 SILC_STATUS_ERR_BAD_PASSWORD);
1786 /* Check user count limit if set. */
1787 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1788 if (silc_list_count(channel->user_list) + 1 >
1789 channel->mode_data.user_limit) {
1790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1791 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1797 * Client is allowed to join to the channel. Make it happen.
1800 /* Get the client entry */
1801 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1802 client = (SilcClientEntry)sock->user_data;
1804 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1807 /* XXX actually this is useless since router finds always cell's
1808 local clients from its local lists. */
1809 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1816 /* Check whether the client already is on the channel */
1817 if (silc_server_client_on_channel(client, channel)) {
1818 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1819 SILC_STATUS_ERR_USER_ON_CHANNEL);
1823 /* Generate new channel key as protocol dictates */
1824 if (!created || !channel->channel_key)
1825 silc_server_create_channel_key(server, channel, 0);
1827 /* Send the channel key. This is broadcasted to the channel but is not
1828 sent to the client who is joining to the channel. */
1829 silc_server_send_channel_key(server, NULL, channel,
1830 server->server_type == SILC_ROUTER ?
1831 FALSE : server->standalone);
1833 /* Join the client to the channel by adding it to channel's user list.
1834 Add also the channel to client entry's channels list for fast cross-
1836 chl = silc_calloc(1, sizeof(*chl));
1838 chl->client = client;
1839 chl->channel = channel;
1840 silc_list_add(channel->user_list, chl);
1841 silc_list_add(client->channels, chl);
1843 /* Encode Client ID Payload of the original client who wants to join */
1844 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1846 /* Encode command reply packet */
1847 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1848 SILC_PUT32_MSB(channel->mode, mode);
1849 SILC_PUT32_MSB(created, tmp2);
1850 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1851 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1852 SILC_ID_CHANNEL_LEN,
1853 channel->channel_key->cipher->name,
1854 channel->key_len / 8, channel->key);
1856 if (!channel->topic) {
1858 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1859 SILC_STATUS_OK, ident, 5,
1860 2, channel->channel_name,
1861 strlen(channel->channel_name),
1862 3, chidp->data, chidp->len,
1865 6, keyp->data, keyp->len);
1868 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1869 SILC_STATUS_OK, ident, 6,
1870 2, channel->channel_name,
1871 strlen(channel->channel_name),
1872 3, chidp->data, chidp->len,
1875 6, keyp->data, keyp->len,
1877 strlen(channel->topic));
1880 /* Send command reply */
1881 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1882 reply->data, reply->len, FALSE);
1884 if (!cmd->pending) {
1885 /* Send JOIN notify to locally connected clients on the channel */
1886 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1887 SILC_NOTIFY_TYPE_JOIN, 1,
1888 clidp->data, clidp->len);
1890 /* Send NEW_CHANNEL_USER packet to our primary router */
1891 if (!server->standalone)
1892 silc_server_send_new_channel_user(server, server->router->connection,
1893 server->server_type == SILC_SERVER ?
1895 channel->id, SILC_ID_CHANNEL_LEN,
1896 client->id, SILC_ID_CLIENT_LEN);
1899 /* Send USERS command reply to the joined channel so the user sees who
1900 is currently on the channel. */
1901 silc_server_command_send_users(server, sock, channel, cmd->pending);
1903 silc_buffer_free(reply);
1904 silc_buffer_free(clidp);
1905 silc_buffer_free(chidp);
1906 silc_buffer_free(keyp);
1910 silc_free(passphrase);
1913 /* Server side of command JOIN. Joins client into requested channel. If
1914 the channel does not exist it will be created. */
1916 SILC_SERVER_CMD_FUNC(join)
1918 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1919 SilcServer server = cmd->server;
1921 char *tmp, *channel_name = NULL, *cipher = NULL;
1922 SilcChannelEntry channel;
1923 unsigned int umode = 0;
1924 int created = FALSE;
1925 SilcClientID *client_id;
1927 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1929 /* Get channel name */
1930 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1932 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1933 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1938 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1939 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1940 SILC_STATUS_ERR_BAD_CHANNEL);
1941 silc_free(channel_name);
1945 /* Get Client ID of the client who is joining to the channel */
1946 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1949 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1952 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1955 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1959 /* Get cipher name */
1960 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
1962 /* See if the channel exists */
1963 channel = silc_idlist_find_channel_by_name(server->local_list,
1964 channel_name, NULL);
1966 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1967 /* If this is coming from client the Client ID in the command packet must
1968 be same as the client's ID. */
1969 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1970 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
1971 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
1972 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1973 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1979 /* Channel not found */
1981 /* If we are standalone server we don't have a router, we just create
1982 the channel by ourselves. */
1983 if (server->standalone) {
1984 channel = silc_server_create_new_channel(server, server->id, cipher,
1986 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1991 /* The channel does not exist on our server. If we are normal server
1992 we will send JOIN command to our router which will handle the
1993 joining procedure (either creates the channel if it doesn't exist
1994 or joins the client to it). */
1995 if (server->server_type == SILC_SERVER) {
1997 unsigned short old_ident;
1999 old_ident = silc_command_get_ident(cmd->payload);
2000 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2001 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2003 /* Send JOIN command to our router */
2004 silc_server_packet_send(server, (SilcSocketConnection)
2005 server->router->connection,
2006 SILC_PACKET_COMMAND, cmd->packet->flags,
2007 tmpbuf->data, tmpbuf->len, TRUE);
2009 /* Reprocess this packet after received reply from router */
2010 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2011 silc_command_get_ident(cmd->payload),
2012 silc_server_command_join, context);
2013 cmd->pending = TRUE;
2017 /* We are router and the channel does not seem exist so we will check
2018 our global list as well for the channel. */
2019 channel = silc_idlist_find_channel_by_name(server->global_list,
2020 channel_name, NULL);
2022 /* Channel really does not exist, create it */
2023 channel = silc_server_create_new_channel(server, server->id, cipher,
2025 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2032 /* Channel not found */
2034 /* If the command came from router and/or we are normal server then
2035 something went wrong with the joining as the channel was not found.
2036 We can't do anything else but ignore this. */
2037 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2038 server->server_type == SILC_SERVER)
2041 /* We are router and the channel does not seem exist so we will check
2042 our global list as well for the channel. */
2043 channel = silc_idlist_find_channel_by_name(server->global_list,
2044 channel_name, NULL);
2046 /* Channel really does not exist, create it */
2047 channel = silc_server_create_new_channel(server, server->id, cipher,
2049 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2055 /* If the channel does not have global users and is also empty it means the
2056 channel was created globally (by our router) and the client will be the
2057 channel founder and operator. */
2058 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2059 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2060 created = TRUE; /* Created globally by our router */
2063 /* Join to the channel */
2064 silc_server_command_join_channel(server, cmd, channel, client_id,
2067 silc_free(client_id);
2070 silc_server_command_free(cmd);
2073 /* Server side of command MOTD. Sends server's current "message of the
2074 day" to the client. */
2076 SILC_SERVER_CMD_FUNC(motd)
2078 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2079 SilcServer server = cmd->server;
2083 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2085 /* XXX show currently only our motd */
2087 if (server->config && server->config->motd &&
2088 server->config->motd->motd_file) {
2091 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2096 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2102 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2107 silc_server_command_free(cmd);
2110 SILC_SERVER_CMD_FUNC(umode)
2114 /* Checks that client has rights to add or remove channel modes. If any
2115 of the checks fails FALSE is returned. */
2117 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2118 SilcChannelClientEntry client,
2121 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2122 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2124 /* Check whether has rights to change anything */
2125 if (!is_op && !is_fo)
2128 /* Check whether has rights to change everything */
2132 /* We know that client is channel operator, check that they are not
2133 changing anything that requires channel founder rights. Rest of the
2134 modes are available automatically for channel operator. */
2136 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2137 if (is_op && !is_fo)
2140 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2141 if (is_op && !is_fo)
2146 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2147 if (is_op && !is_fo)
2150 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2151 if (is_op && !is_fo)
2156 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2157 if (is_op && !is_fo)
2160 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2161 if (is_op && !is_fo)
2169 /* Server side command of CMODE. Changes channel mode */
2171 SILC_SERVER_CMD_FUNC(cmode)
2173 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2174 SilcServer server = cmd->server;
2175 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2176 SilcChannelID *channel_id;
2177 SilcChannelEntry channel;
2178 SilcChannelClientEntry chl;
2179 SilcBuffer packet, cidp;
2180 unsigned char *tmp, *tmp_id, *tmp_mask;
2181 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2183 SILC_LOG_DEBUG(("Start"));
2185 argc = silc_argument_get_arg_num(cmd->args);
2187 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2188 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2193 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2197 /* Get Channel ID */
2198 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2200 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2201 SILC_STATUS_ERR_NO_CHANNEL_ID);
2204 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2206 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2207 SILC_STATUS_ERR_NO_CHANNEL_ID);
2211 /* Get the channel mode mask */
2212 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2214 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2215 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2218 SILC_GET32_MSB(mode_mask, tmp_mask);
2220 /* Get channel entry */
2221 channel = silc_idlist_find_channel_by_id(server->local_list,
2224 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2225 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2229 /* Check whether this client is on the channel */
2230 if (!silc_server_client_on_channel(client, channel)) {
2231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2232 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2236 /* Get entry to the channel user list */
2237 silc_list_start(channel->user_list);
2238 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2239 if (chl->client == client)
2242 /* Check that client has rights to change any requested channel modes */
2243 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2245 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2250 * Check the modes. Modes that requires nothing special operation are
2254 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2255 /* Channel uses private keys to protect traffic. Client(s) has set the
2256 key locally they want to use, server does not know that key. */
2257 /* Nothing interesting to do here now */
2259 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2260 /* The mode is removed and we need to generate and distribute
2261 new channel key. Clients are not using private channel keys
2262 anymore after this. */
2264 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2267 /* Re-generate channel key */
2268 silc_server_create_channel_key(server, channel, 0);
2270 /* Encode channel key payload to be distributed on the channel */
2272 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2273 strlen(channel->channel_key->
2275 channel->channel_key->cipher->name,
2276 channel->key_len / 8, channel->key);
2278 /* If we are normal server then we will send it to our router. If we
2279 are router we will send it to all local servers that has clients on
2281 if (server->server_type == SILC_SERVER) {
2282 if (!server->standalone)
2283 silc_server_packet_send(server,
2284 cmd->server->router->connection,
2285 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2291 /* Send to locally connected clients on the channel */
2292 silc_server_packet_send_local_channel(server, channel,
2293 SILC_PACKET_CHANNEL_KEY, 0,
2294 packet->data, packet->len, FALSE);
2295 silc_buffer_free(packet);
2299 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2300 /* User limit is set on channel */
2301 unsigned int user_limit;
2303 /* Get user limit */
2304 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2306 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2308 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2312 SILC_GET32_MSB(user_limit, tmp);
2313 channel->mode_data.user_limit = user_limit;
2316 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2317 /* User limit mode is unset. Remove user limit */
2318 channel->mode_data.user_limit = 0;
2321 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2322 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2323 /* Passphrase has been set to channel */
2325 /* Get the passphrase */
2326 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2329 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2333 /* Save the passphrase */
2334 channel->mode_data.passphrase = strdup(tmp);
2337 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2338 /* Passphrase mode is unset. remove the passphrase */
2339 if (channel->mode_data.passphrase) {
2340 silc_free(channel->mode_data.passphrase);
2341 channel->mode_data.passphrase = NULL;
2346 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2347 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2348 /* Ban list is specified for channel */
2351 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2354 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2358 /* XXX check that channel founder is not banned */
2360 /* Save the ban list */
2361 channel->mode_data.ban_list = strdup(tmp);
2364 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2365 /* Ban mode is unset. Remove the entire ban list */
2366 if (channel->mode_data.ban_list) {
2367 silc_free(channel->mode_data.ban_list);
2368 channel->mode_data.ban_list = NULL;
2373 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2374 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2375 /* Invite list is specified for channel */
2377 /* Get invite list */
2378 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2380 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2381 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2385 /* Save the invite linst */
2386 channel->mode_data.invite_list = strdup(tmp);
2389 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2390 /* Invite list mode is unset. Remove the entire invite list */
2391 if (channel->mode_data.invite_list) {
2392 silc_free(channel->mode_data.invite_list);
2393 channel->mode_data.invite_list = NULL;
2398 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2399 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2400 /* Cipher to use protect the traffic */
2401 unsigned int key_len = 128;
2405 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2408 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2412 cp = strchr(tmp, ':');
2418 /* XXX Duplicated code, make own function for this!! */
2420 /* Delete old cipher and allocate the new one */
2421 silc_cipher_free(channel->channel_key);
2422 silc_cipher_alloc(tmp, &channel->channel_key);
2428 /* Re-generate channel key */
2429 silc_server_create_channel_key(server, channel, key_len);
2431 /* Encode channel key payload to be distributed on the channel */
2433 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2434 strlen(channel->channel_key->
2436 channel->channel_key->cipher->name,
2437 channel->key_len / 8, channel->key);
2439 /* If we are normal server then we will send it to our router. If we
2440 are router we will send it to all local servers that has clients on
2442 if (server->server_type == SILC_SERVER) {
2443 if (!server->standalone)
2444 silc_server_packet_send(server,
2445 cmd->server->router->connection,
2446 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2452 /* Send to locally connected clients on the channel */
2453 silc_server_packet_send_local_channel(server, channel,
2454 SILC_PACKET_CHANNEL_KEY, 0,
2455 packet->data, packet->len, FALSE);
2456 silc_buffer_free(packet);
2459 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2460 /* Cipher mode is unset. Remove the cipher and revert back to
2463 if (channel->mode_data.cipher) {
2464 silc_free(channel->mode_data.cipher);
2465 channel->mode_data.cipher = NULL;
2466 channel->mode_data.key_len = 0;
2469 /* Generate new cipher and key for the channel */
2471 /* XXX Duplicated code, make own function for this!! */
2473 /* Delete old cipher and allocate default one */
2474 silc_cipher_free(channel->channel_key);
2475 if (!channel->cipher)
2476 silc_cipher_alloc("twofish", &channel->channel_key);
2478 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2480 /* Re-generate channel key */
2481 silc_server_create_channel_key(server, channel, 0);
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);
2512 /* Finally, set the mode */
2513 channel->mode = mode_mask;
2515 /* Send CMODE_CHANGE notify */
2516 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2517 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2518 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2519 cidp->data, cidp->len,
2523 /* Send command reply to sender */
2524 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2525 SILC_STATUS_OK, 0, 1,
2527 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2528 packet->data, packet->len, FALSE);
2530 silc_buffer_free(packet);
2531 silc_free(channel_id);
2534 silc_server_command_free(cmd);
2537 /* Server side of CUMODE command. Changes client's mode on a channel. */
2539 SILC_SERVER_CMD_FUNC(cumode)
2541 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2542 SilcServer server = cmd->server;
2543 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2544 SilcChannelID *channel_id;
2545 SilcClientID *client_id;
2546 SilcChannelEntry channel;
2547 SilcClientEntry target_client;
2548 SilcChannelClientEntry chl;
2549 SilcBuffer packet, idp;
2550 unsigned char *tmp_id, *tmp_mask;
2551 unsigned int target_mask, sender_mask, tmp_len;
2554 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2556 /* Get Channel ID */
2557 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2560 SILC_STATUS_ERR_NO_CHANNEL_ID);
2563 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2565 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2566 SILC_STATUS_ERR_NO_CHANNEL_ID);
2570 /* Get channel entry */
2571 channel = silc_idlist_find_channel_by_id(server->local_list,
2574 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2575 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2579 /* Check whether sender is on the channel */
2580 if (!silc_server_client_on_channel(client, channel)) {
2581 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2582 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2586 /* Check that client has rights to change other's rights */
2587 silc_list_start(channel->user_list);
2588 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2589 if (chl->client == client) {
2590 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2591 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2592 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2593 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2597 sender_mask = chl->mode;
2602 /* Get the target client's channel mode mask */
2603 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2605 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2606 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2609 SILC_GET32_MSB(target_mask, tmp_mask);
2611 /* Get target Client ID */
2612 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2615 SILC_STATUS_ERR_NO_CHANNEL_ID);
2618 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2620 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2621 SILC_STATUS_ERR_NO_CHANNEL_ID);
2625 /* Get target client's entry */
2626 target_client = silc_idlist_find_client_by_id(server->local_list,
2628 if (!target_client) {
2629 /* XXX If target client is not one of mine send to primary route */
2632 /* Check whether target client is on the channel */
2633 if (!silc_server_client_on_channel(target_client, channel)) {
2634 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2635 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2639 /* Get entry to the channel user list */
2640 silc_list_start(channel->user_list);
2641 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2642 if (chl->client == target_client)
2649 /* If the target client is founder, no one else can change their mode
2651 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2653 SILC_STATUS_ERR_NOT_YOU);
2657 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2658 /* Cannot promote anyone to channel founder */
2659 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2660 SILC_STATUS_ERR_NOT_YOU);
2663 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2664 if (target_client == client) {
2665 /* Remove channel founder rights from itself */
2666 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2670 SILC_STATUS_ERR_NOT_YOU);
2676 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2677 /* Promote to operator */
2678 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2679 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2683 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2684 /* Demote to normal user */
2685 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2690 /* Send notify to channel, notify only if mode was actually changed. */
2692 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2693 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2694 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2695 idp->data, idp->len,
2696 tmp_mask, 4, tmp_id, tmp_len);
2697 silc_buffer_free(idp);
2700 /* Send command reply to sender */
2701 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2702 SILC_STATUS_OK, 0, 2,
2704 3, tmp_id, tmp_len);
2705 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2706 packet->data, packet->len, FALSE);
2708 silc_buffer_free(packet);
2709 silc_free(channel_id);
2710 silc_free(client_id);
2713 silc_server_command_free(cmd);
2716 /* Server side of KICK command. Kicks client out of channel. */
2718 SILC_SERVER_CMD_FUNC(kick)
2722 SILC_SERVER_CMD_FUNC(restart)
2726 SILC_SERVER_CMD_FUNC(close)
2730 SILC_SERVER_CMD_FUNC(die)
2734 SILC_SERVER_CMD_FUNC(silcoper)
2738 /* Server side command of LEAVE. Removes client from a channel. */
2740 SILC_SERVER_CMD_FUNC(leave)
2742 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2743 SilcServer server = cmd->server;
2744 SilcSocketConnection sock = cmd->sock;
2745 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2747 SilcChannelEntry channel;
2749 unsigned int i, len;
2752 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2754 /* Get Channel ID */
2755 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2757 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2758 SILC_STATUS_ERR_NO_CHANNEL_ID);
2761 id = silc_id_payload_parse_id(tmp, len);
2763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2764 SILC_STATUS_ERR_NO_CHANNEL_ID);
2768 /* Get channel entry */
2769 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2771 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2772 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2776 /* Check whether this client is on the channel */
2777 if (!silc_server_client_on_channel(id_entry, channel)) {
2778 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2779 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2783 /* Notify routers that they should remove this client from their list
2784 of clients on the channel. */
2785 if (!server->standalone)
2786 silc_server_send_remove_channel_user(server,
2787 server->router->connection,
2788 server->server_type == SILC_ROUTER ?
2789 TRUE : FALSE, id_entry->id, id);
2791 /* Remove client from channel */
2792 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2794 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2797 /* If the channel does not exist anymore we won't send anything */
2801 /* Re-generate channel key */
2802 silc_server_create_channel_key(server, channel, 0);
2804 /* Encode channel key payload to be distributed on the channel */
2806 silc_channel_key_payload_encode(len, tmp,
2807 strlen(channel->channel_key->cipher->name),
2808 channel->channel_key->cipher->name,
2809 channel->key_len / 8, channel->key);
2811 /* If we are normal server then we will send it to our router. If we
2812 are router we will send it to all local servers that has clients on
2814 if (server->server_type == SILC_SERVER) {
2815 if (!server->standalone)
2816 silc_server_packet_send(server,
2817 cmd->server->router->connection,
2818 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2824 /* Send to locally connected clients on the channel */
2825 silc_server_packet_send_local_channel(server, channel,
2826 SILC_PACKET_CHANNEL_KEY, 0,
2827 packet->data, packet->len, FALSE);
2829 silc_buffer_free(packet);
2833 silc_server_command_free(cmd);
2836 /* Server side of command USERS. Resolves clients and their USERS currently
2837 joined on the requested channel. The list of Client ID's and their modes
2838 on the channel is sent back. */
2840 SILC_SERVER_CMD_FUNC(users)
2842 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2843 SilcServer server = cmd->server;
2844 SilcChannelEntry channel;
2845 SilcChannelClientEntry chl;
2848 unsigned char *channel_id;
2849 unsigned int channel_id_len;
2850 SilcBuffer client_id_list;
2851 SilcBuffer client_mode_list;
2853 unsigned char lc[4];
2854 unsigned int list_count = 0;
2855 unsigned short ident = silc_command_get_ident(cmd->payload);
2857 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
2859 /* Get Channel ID */
2860 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
2862 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2863 SILC_STATUS_ERR_NO_CHANNEL_ID);
2866 id = silc_id_payload_parse_id(channel_id, channel_id_len);
2868 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2869 SILC_STATUS_ERR_NO_CHANNEL_ID);
2873 /* If we are server and we don't know about this channel we will send
2874 the command to our router. If we know about the channel then we also
2875 have the list of users already. */
2876 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2878 if (server->server_type == SILC_SERVER && !server->standalone &&
2882 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2883 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2885 /* Send USERS command */
2886 silc_server_packet_send(server, server->router->connection,
2887 SILC_PACKET_COMMAND, cmd->packet->flags,
2888 tmpbuf->data, tmpbuf->len, TRUE);
2890 /* Reprocess this packet after received reply */
2891 silc_server_command_pending(server, SILC_COMMAND_USERS,
2892 silc_command_get_ident(cmd->payload),
2893 silc_server_command_users, (void *)cmd);
2894 cmd->pending = TRUE;
2895 silc_command_set_ident(cmd->payload, ident);
2897 silc_buffer_free(tmpbuf);
2902 /* We are router and we will check the global list as well. */
2903 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2905 /* Channel really does not exist */
2906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2907 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2912 /* Assemble the lists now */
2914 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2915 silc_list_count(channel->user_list));
2916 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2918 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2919 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2921 silc_list_start(channel->user_list);
2922 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2924 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2925 silc_buffer_put(client_id_list, idp->data, idp->len);
2926 silc_buffer_pull(client_id_list, idp->len);
2927 silc_buffer_free(idp);
2929 /* Client's mode on channel */
2930 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2931 silc_buffer_pull(client_mode_list, 4);
2935 silc_buffer_push(client_id_list,
2936 client_id_list->data - client_id_list->head);
2937 silc_buffer_push(client_mode_list,
2938 client_mode_list->data - client_mode_list->head);
2941 SILC_PUT32_MSB(list_count, lc);
2944 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
2945 SILC_STATUS_OK, 0, 4,
2946 2, channel_id, channel_id_len,
2948 4, client_id_list->data,
2949 client_id_list->len,
2950 5, client_mode_list->data,
2951 client_mode_list->len);
2952 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2953 packet->data, packet->len, FALSE);
2955 silc_buffer_free(packet);
2956 silc_buffer_free(client_id_list);
2957 silc_buffer_free(client_mode_list);
2961 silc_server_command_free(cmd);