5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
37 unsigned int arg_type,
39 unsigned int arg_len);
40 void silc_server_command_send_users(SilcServer server,
41 SilcSocketConnection sock,
42 SilcChannelEntry channel,
45 /* Server command list. */
46 SilcServerCommand silc_command_list[] =
48 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
49 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
54 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(connect, CONNECT,
59 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
60 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
62 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(restart, RESTART,
69 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
70 SILC_SERVER_CMD(close, CLOSE,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72 SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
73 SILC_SERVER_CMD(silcoper, SILCOPER,
74 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
75 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
76 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
81 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
83 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
85 SILC_LOG_DEBUG(("Start")); \
88 silc_server_command_send_status_reply(cmd, command, \
89 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
90 silc_server_command_free(cmd); \
94 silc_server_command_send_status_reply(cmd, command, \
95 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
96 silc_server_command_free(cmd); \
101 /* Returns TRUE if the connection is registered. Unregistered connections
102 usually cannot send commands hence the check. */
104 static int silc_server_is_registered(SilcServer server,
105 SilcSocketConnection sock,
106 SilcServerCommandContext cmd,
109 SilcIDListData idata = (SilcIDListData)sock->user_data;
110 if (idata->registered)
113 silc_server_command_send_status_reply(cmd, command,
114 SILC_STATUS_ERR_NOT_REGISTERED);
115 silc_server_command_free(cmd);
119 /* Processes received command packet. */
121 void silc_server_command_process(SilcServer server,
122 SilcSocketConnection sock,
123 SilcPacketContext *packet)
125 SilcServerCommandContext ctx;
126 SilcServerCommand *cmd;
129 /* XXX allow commands in but do not execute them more than once per
132 /* Check whether it is allowed for this connection to execute any
134 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
136 SilcClientEntry client = (SilcClientEntry)sock->user_data;
141 /* Allow only one command executed in 2 seconds. */
142 curtime = time(NULL);
143 if (client->last_command && (curtime - client->last_command) < 2)
146 /* Update access time */
147 client->last_command = curtime;
151 /* Allocate command context. This must be free'd by the
152 command routine receiving it. */
153 ctx = silc_server_command_alloc();
154 ctx->server = server;
155 ctx->sock = silc_socket_dup(sock);
156 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
158 /* Parse the command payload in the packet */
159 ctx->payload = silc_command_payload_parse(packet->buffer);
161 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
162 silc_buffer_free(packet->buffer);
163 silc_packet_context_free(packet);
164 silc_socket_free(ctx->sock);
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 /* Allocate Command Context */
194 SilcServerCommandContext silc_server_command_alloc()
196 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
201 /* Free's the command context allocated before executing the command */
203 void silc_server_command_free(SilcServerCommandContext ctx)
206 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
208 if (ctx->users < 1) {
210 silc_command_free_payload(ctx->payload);
212 silc_packet_context_free(ctx->packet);
214 silc_socket_free(ctx->sock); /* Decrease reference counter */
219 /* Duplicate Command Context by adding reference counter. The context won't
220 be free'd untill it hits zero. */
222 SilcServerCommandContext
223 silc_server_command_dup(SilcServerCommandContext ctx)
226 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
231 /* Add new pending command to be executed when reply to a command has been
232 received. The `reply_cmd' is the command that will call the `callback'
233 with `context' when reply has been received. If `ident' is non-zero
234 the `callback' will be executed when received reply with command
235 identifier `ident'. */
237 void silc_server_command_pending(SilcServer server,
238 SilcCommand reply_cmd,
239 unsigned short ident,
240 SilcServerPendingDestructor destructor,
241 SilcCommandCb callback,
244 SilcServerCommandPending *reply;
246 reply = silc_calloc(1, sizeof(*reply));
247 reply->reply_cmd = reply_cmd;
248 reply->ident = ident;
249 reply->context = context;
250 reply->callback = callback;
251 reply->destructor = destructor;
252 silc_dlist_add(server->pending_commands, reply);
255 /* Deletes pending command by reply command type. */
257 void silc_server_command_pending_del(SilcServer server,
258 SilcCommand reply_cmd,
259 unsigned short ident)
261 SilcServerCommandPending *r;
263 silc_dlist_start(server->pending_commands);
264 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
265 if (r->reply_cmd == reply_cmd && r->ident == ident) {
266 silc_dlist_del(server->pending_commands, r);
272 /* Checks for pending commands and marks callbacks to be called from
273 the command reply function. Returns TRUE if there were pending command. */
275 int silc_server_command_pending_check(SilcServer server,
276 SilcServerCommandReplyContext ctx,
278 unsigned short ident)
280 SilcServerCommandPending *r;
282 silc_dlist_start(server->pending_commands);
283 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
284 if (r->reply_cmd == command && r->ident == ident) {
285 ctx->context = r->context;
286 ctx->callback = r->callback;
287 ctx->destructor = r->destructor;
296 /* Destructor function for pending callbacks. This is called when using
297 pending commands to free the context given for the pending command. */
299 static void silc_server_command_destructor(void *context)
301 silc_server_command_free((SilcServerCommandContext)context);
304 /* Sends simple status message as command reply packet */
307 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
309 SilcCommandStatus status)
313 SILC_LOG_DEBUG(("Sending command status %d", status));
315 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
316 silc_server_packet_send(cmd->server, cmd->sock,
317 SILC_PACKET_COMMAND_REPLY, 0,
318 buffer->data, buffer->len, FALSE);
319 silc_buffer_free(buffer);
322 /* Sends command status reply with one extra argument. The argument
323 type must be sent as argument. */
326 silc_server_command_send_status_data(SilcServerCommandContext cmd,
328 SilcCommandStatus status,
329 unsigned int arg_type,
331 unsigned int arg_len)
335 SILC_LOG_DEBUG(("Sending command status %d", status));
337 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
338 arg_type, arg, arg_len);
339 silc_server_packet_send(cmd->server, cmd->sock,
340 SILC_PACKET_COMMAND_REPLY, 0,
341 buffer->data, buffer->len, FALSE);
342 silc_buffer_free(buffer);
345 /******************************************************************************
349 ******************************************************************************/
352 silc_server_command_whois_parse(SilcServerCommandContext cmd,
353 SilcClientID ***client_id,
354 unsigned int *client_id_count,
362 unsigned int argc = silc_argument_get_arg_num(cmd->args);
365 /* If client ID is in the command it must be used instead of nickname */
366 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
368 /* No ID, get the nickname@server string and parse it. */
369 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
371 if (strchr(tmp, '@')) {
372 len = strcspn(tmp, "@");
373 *nickname = silc_calloc(len + 1, sizeof(char));
374 memcpy(*nickname, tmp, len);
375 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
376 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
378 *nickname = strdup(tmp);
381 silc_server_command_send_status_reply(cmd, command,
382 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
386 /* Command includes ID, we must use that. Also check whether the command
387 has more than one ID set - take them all. */
389 *client_id = silc_calloc(1, sizeof(**client_id));
390 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
391 if ((*client_id)[0] == NULL) {
392 silc_free(*client_id);
395 *client_id_count = 1;
397 /* Take all ID's from the command packet */
399 for (k = 1, i = 4; i < argc + 1; i++) {
400 tmp = silc_argument_get_arg_type(cmd->args, i, &len);
402 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
403 (*client_id_count + 1));
404 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
405 if ((*client_id)[k] == NULL) {
406 /* Cleanup all and fail */
407 for (i = 0; i < *client_id_count; i++)
408 silc_free((*client_id)[i]);
409 silc_free(*client_id);
412 (*client_id_count)++;
418 /* Command includes ID, use that */
421 /* Get the max count of reply messages allowed */
422 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
432 silc_server_command_whois_check(SilcServerCommandContext cmd,
433 SilcClientEntry *clients,
434 unsigned int clients_count)
436 SilcServer server = cmd->server;
438 SilcClientEntry entry;
440 for (i = 0; i < clients_count; i++) {
443 if (!entry->nickname || !entry->username) {
445 unsigned short old_ident;
450 old_ident = silc_command_get_ident(cmd->payload);
451 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
452 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
454 /* Send WHOIS command */
455 silc_server_packet_send(server, entry->router->connection,
456 SILC_PACKET_COMMAND, cmd->packet->flags,
457 tmpbuf->data, tmpbuf->len, TRUE);
459 /* Reprocess this packet after received reply */
460 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
461 silc_command_get_ident(cmd->payload),
462 silc_server_command_destructor,
463 silc_server_command_whois,
464 silc_server_command_dup(cmd));
467 silc_command_set_ident(cmd->payload, old_ident);
469 silc_buffer_free(tmpbuf);
478 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
479 SilcClientEntry *clients,
480 unsigned int clients_count)
482 SilcServer server = cmd->server;
484 int i, count = 0, len;
485 SilcBuffer packet, idp;
486 SilcClientEntry entry;
487 SilcCommandStatus status;
488 unsigned short ident = silc_command_get_ident(cmd->payload);
490 status = SILC_STATUS_OK;
491 if (clients_count > 1)
492 status = SILC_STATUS_LIST_START;
494 for (i = 0; i < clients_count; i++) {
497 if (count && i - 1 == count)
500 if (clients_count > 2)
501 status = SILC_STATUS_LIST_ITEM;
503 if (clients_count > 1 && i == clients_count - 1)
504 status = SILC_STATUS_LIST_END;
506 /* Sanity check, however these should never fail. However, as
507 this sanity check has been added here they have failed. */
508 if (!entry->nickname || !entry->username)
511 /* Send WHOIS reply */
512 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
513 tmp = silc_argument_get_first_arg(cmd->args, NULL);
517 char nh[256], uh[256];
518 unsigned char idle[4];
519 SilcSocketConnection hsock;
521 memset(uh, 0, sizeof(uh));
522 memset(nh, 0, sizeof(nh));
524 strncat(nh, entry->nickname, strlen(entry->nickname));
525 if (!strchr(entry->nickname, '@')) {
527 len = entry->router ? strlen(entry->router->server_name) :
528 strlen(server->server_name);
529 strncat(nh, entry->router ? entry->router->server_name :
530 server->server_name, len);
533 strncat(uh, entry->username, strlen(entry->username));
534 if (!strchr(entry->username, '@')) {
536 hsock = (SilcSocketConnection)entry->connection;
537 len = strlen(hsock->hostname);
538 strncat(uh, hsock->hostname, len);
541 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
546 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
548 2, idp->data, idp->len,
552 strlen(entry->userinfo),
556 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
558 2, idp->data, idp->len,
564 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
565 0, packet->data, packet->len, FALSE);
567 silc_buffer_free(packet);
568 silc_buffer_free(idp);
573 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
575 SilcServer server = cmd->server;
576 char *nick = NULL, *server_name = NULL;
577 int count = 0, clients_count = 0;
578 SilcClientEntry *clients = NULL, entry;
579 SilcClientID **client_id = NULL;
580 unsigned int client_id_count = 0;
583 /* Protocol dictates that we must always send the received WHOIS request
584 to our router if we are normal server, so let's do it now unless we
585 are standalone. We will not send any replies to the client until we
586 have received reply from the router. */
587 if (server->server_type == SILC_SERVER &&
588 !cmd->pending && !server->standalone) {
590 unsigned short old_ident;
592 old_ident = silc_command_get_ident(cmd->payload);
593 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
594 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
596 /* Send WHOIS command to our router */
597 silc_server_packet_send(server, (SilcSocketConnection)
598 server->router->connection,
599 SILC_PACKET_COMMAND, cmd->packet->flags,
600 tmpbuf->data, tmpbuf->len, TRUE);
602 /* Reprocess this packet after received reply from router */
603 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
604 silc_command_get_ident(cmd->payload),
605 silc_server_command_destructor,
606 silc_server_command_whois,
607 silc_server_command_dup(cmd));
610 silc_command_set_ident(cmd->payload, old_ident);
612 silc_buffer_free(tmpbuf);
617 /* We are ready to process the command request. Let's search for the
618 requested client and send reply to the requesting client. */
620 /* Parse the whois request */
621 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
622 &nick, &server_name, &count,
626 /* Get all clients matching that ID or nickname from local list */
627 if (client_id_count) {
628 /* Check all Client ID's received in the command packet */
629 for (i = 0; i < client_id_count; i++) {
630 entry = silc_idlist_find_client_by_id(server->local_list,
633 clients = silc_realloc(clients, sizeof(*clients) *
634 (clients_count + 1));
635 clients[clients_count++] = entry;
639 clients = silc_idlist_get_clients_by_nickname(server->local_list,
644 /* Check global list as well */
646 if (client_id_count) {
647 /* Check all Client ID's received in the command packet */
648 for (i = 0; i < client_id_count; i++) {
649 entry = silc_idlist_find_client_by_id(server->global_list,
652 clients = silc_realloc(clients, sizeof(*clients) *
653 (clients_count + 1));
654 clients[clients_count++] = entry;
658 clients = silc_idlist_get_clients_by_nickname(server->global_list,
665 /* Such client(s) really does not exist in the SILC network. */
666 if (!client_id_count) {
667 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
668 SILC_STATUS_ERR_NO_SUCH_NICK,
669 3, nick, strlen(nick));
671 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
672 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
673 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
674 2, idp->data, idp->len);
675 silc_buffer_free(idp);
680 /* Router always finds the client entry if it exists in the SILC network.
681 However, it might be incomplete entry and does not include all the
682 mandatory fields that WHOIS command reply requires. Check for these and
683 make query from the server who owns the client if some fields are
685 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
690 /* Send the command reply to the client */
691 silc_server_command_whois_send_reply(cmd, clients, clients_count);
694 if (client_id_count) {
695 for (i = 0; i < client_id_count; i++)
696 silc_free(client_id[i]);
697 silc_free(client_id);
704 silc_free(server_name);
710 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
712 SilcServer server = cmd->server;
713 char *nick = NULL, *server_name = NULL;
714 int count = 0, clients_count = 0;
715 SilcClientEntry *clients = NULL, entry;
716 SilcClientID **client_id = NULL;
717 unsigned int client_id_count = 0;
720 /* Parse the whois request */
721 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
722 &nick, &server_name, &count,
726 /* Process the command request. Let's search for the requested client and
727 send reply to the requesting server. */
729 if (client_id_count) {
730 /* Check all Client ID's received in the command packet */
731 for (i = 0; i < client_id_count; i++) {
732 entry = silc_idlist_find_client_by_id(server->local_list,
735 clients = silc_realloc(clients, sizeof(*clients) *
736 (clients_count + 1));
737 clients[clients_count++] = entry;
741 clients = silc_idlist_get_clients_by_nickname(server->local_list,
745 clients = silc_idlist_get_clients_by_hash(server->local_list,
746 nick, server->md5hash,
750 /* If we are router we will check our global list as well. */
751 if (!clients && server->server_type == SILC_ROUTER) {
752 if (client_id_count) {
753 /* Check all Client ID's received in the command packet */
754 for (i = 0; i < client_id_count; i++) {
755 entry = silc_idlist_find_client_by_id(server->global_list,
758 clients = silc_realloc(clients, sizeof(*clients) *
759 (clients_count + 1));
760 clients[clients_count++] = entry;
764 clients = silc_idlist_get_clients_by_nickname(server->global_list,
768 clients = silc_idlist_get_clients_by_hash(server->global_list,
769 nick, server->md5hash,
775 /* Such a client really does not exist in the SILC network. */
776 if (!client_id_count) {
777 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
778 SILC_STATUS_ERR_NO_SUCH_NICK,
779 3, nick, strlen(nick));
781 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
782 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
783 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
784 2, idp->data, idp->len);
785 silc_buffer_free(idp);
790 /* Router always finds the client entry if it exists in the SILC network.
791 However, it might be incomplete entry and does not include all the
792 mandatory fields that WHOIS command reply requires. Check for these and
793 make query from the server who owns the client if some fields are
795 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
800 /* Send the command reply to the client */
801 silc_server_command_whois_send_reply(cmd, clients, clients_count);
804 if (client_id_count) {
805 for (i = 0; i < client_id_count; i++)
806 silc_free(client_id[i]);
807 silc_free(client_id);
814 silc_free(server_name);
819 /* Server side of command WHOIS. Processes user's query and sends found
820 results as command replies back to the client. */
822 SILC_SERVER_CMD_FUNC(whois)
824 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
827 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
829 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
830 ret = silc_server_command_whois_from_client(cmd);
831 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
832 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
833 ret = silc_server_command_whois_from_server(cmd);
836 silc_server_command_free(cmd);
839 SILC_SERVER_CMD_FUNC(whowas)
843 /******************************************************************************
847 ******************************************************************************/
849 /* Checks that all mandatory fields are present. If not then send WHOIS
850 request to the server who owns the client. We use WHOIS because we want
851 to get as much information as possible at once. */
854 silc_server_command_identify_check(SilcServerCommandContext cmd,
855 SilcClientEntry *clients,
856 unsigned int clients_count)
858 SilcServer server = cmd->server;
860 SilcClientEntry entry;
862 for (i = 0; i < clients_count; i++) {
865 if (!entry->nickname) {
867 unsigned short old_ident;
872 old_ident = silc_command_get_ident(cmd->payload);
873 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
874 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
875 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
877 /* Send WHOIS request. We send WHOIS since we're doing the requesting
878 now anyway so make it a good one. */
879 silc_server_packet_send(server, entry->router->connection,
880 SILC_PACKET_COMMAND, cmd->packet->flags,
881 tmpbuf->data, tmpbuf->len, TRUE);
883 /* Reprocess this packet after received reply */
884 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
885 silc_command_get_ident(cmd->payload),
886 silc_server_command_destructor,
887 silc_server_command_identify,
888 silc_server_command_dup(cmd));
892 /* Put old data back to the Command Payload we just changed */
893 silc_command_set_ident(cmd->payload, old_ident);
894 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
896 silc_buffer_free(tmpbuf);
905 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
906 SilcClientEntry *clients,
907 unsigned int clients_count)
909 SilcServer server = cmd->server;
911 int i, count = 0, len;
912 SilcBuffer packet, idp;
913 SilcClientEntry entry;
914 SilcCommandStatus status;
915 unsigned short ident = silc_command_get_ident(cmd->payload);
917 status = SILC_STATUS_OK;
918 if (clients_count > 1)
919 status = SILC_STATUS_LIST_START;
921 for (i = 0; i < clients_count; i++) {
924 if (count && i - 1 == count)
927 if (clients_count > 2)
928 status = SILC_STATUS_LIST_ITEM;
930 if (clients_count > 1 && i == clients_count - 1)
931 status = SILC_STATUS_LIST_END;
933 /* Send IDENTIFY reply */
934 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
935 tmp = silc_argument_get_first_arg(cmd->args, NULL);
939 char nh[256], uh[256];
940 SilcSocketConnection hsock;
942 memset(uh, 0, sizeof(uh));
943 memset(nh, 0, sizeof(nh));
945 strncat(nh, entry->nickname, strlen(entry->nickname));
946 if (!strchr(entry->nickname, '@')) {
948 len = entry->router ? strlen(entry->router->server_name) :
949 strlen(server->server_name);
950 strncat(nh, entry->router ? entry->router->server_name :
951 server->server_name, len);
954 if (!entry->username) {
955 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
956 SILC_STATUS_OK, ident, 2,
957 2, idp->data, idp->len,
960 strncat(uh, entry->username, strlen(entry->username));
961 if (!strchr(entry->username, '@')) {
963 hsock = (SilcSocketConnection)entry->connection;
964 len = strlen(hsock->hostname);
965 strncat(uh, hsock->hostname, len);
968 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
969 SILC_STATUS_OK, ident, 3,
970 2, idp->data, idp->len,
975 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
976 0, packet->data, packet->len, FALSE);
978 silc_buffer_free(packet);
979 silc_buffer_free(idp);
985 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
987 SilcServer server = cmd->server;
988 char *nick = NULL, *server_name = NULL;
989 int count = 0, clients_count = 0;
990 SilcClientEntry *clients = NULL, entry;
991 SilcClientID **client_id = NULL;
992 unsigned int client_id_count = 0;
995 /* Protocol dictates that we must always send the received IDENTIFY request
996 to our router if we are normal server, so let's do it now unless we
997 are standalone. We will not send any replies to the client until we
998 have received reply from the router. */
999 if (server->server_type == SILC_SERVER &&
1000 !cmd->pending && !server->standalone) {
1002 unsigned short old_ident;
1004 old_ident = silc_command_get_ident(cmd->payload);
1005 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1006 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1008 /* Send IDENTIFY command to our router */
1009 silc_server_packet_send(server, (SilcSocketConnection)
1010 server->router->connection,
1011 SILC_PACKET_COMMAND, cmd->packet->flags,
1012 tmpbuf->data, tmpbuf->len, TRUE);
1014 /* Reprocess this packet after received reply from router */
1015 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1016 silc_command_get_ident(cmd->payload),
1017 silc_server_command_destructor,
1018 silc_server_command_identify,
1019 silc_server_command_dup(cmd));
1020 cmd->pending = TRUE;
1022 silc_command_set_ident(cmd->payload, old_ident);
1024 silc_buffer_free(tmpbuf);
1029 /* We are ready to process the command request. Let's search for the
1030 requested client and send reply to the requesting client. */
1032 /* Parse the IDENTIFY request */
1033 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1034 &nick, &server_name, &count,
1035 SILC_COMMAND_IDENTIFY))
1038 /* Get all clients matching that ID or nickname from local list */
1039 if (client_id_count) {
1040 /* Check all Client ID's received in the command packet */
1041 for (i = 0; i < client_id_count; i++) {
1042 entry = silc_idlist_find_client_by_id(server->local_list,
1043 client_id[i], NULL);
1045 clients = silc_realloc(clients, sizeof(*clients) *
1046 (clients_count + 1));
1047 clients[clients_count++] = entry;
1051 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1056 /* Check global list as well */
1058 if (client_id_count) {
1059 /* Check all Client ID's received in the command packet */
1060 for (i = 0; i < client_id_count; i++) {
1061 entry = silc_idlist_find_client_by_id(server->global_list,
1062 client_id[i], NULL);
1064 clients = silc_realloc(clients, sizeof(*clients) *
1065 (clients_count + 1));
1066 clients[clients_count++] = entry;
1070 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1077 /* Such a client really does not exist in the SILC network. */
1078 if (!client_id_count) {
1079 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1080 SILC_STATUS_ERR_NO_SUCH_NICK,
1081 3, nick, strlen(nick));
1083 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1084 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1085 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1086 2, idp->data, idp->len);
1087 silc_buffer_free(idp);
1092 /* Check that all mandatory fields are present and request those data
1093 from the server who owns the client if necessary. */
1094 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1099 /* Send the command reply to the client */
1100 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1103 if (client_id_count) {
1104 for (i = 0; i < client_id_count; i++)
1105 silc_free(client_id[i]);
1106 silc_free(client_id);
1113 silc_free(server_name);
1119 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1121 SilcServer server = cmd->server;
1122 char *nick = NULL, *server_name = NULL;
1123 int count = 0, clients_count = 0;
1124 SilcClientEntry *clients = NULL, entry;
1125 SilcClientID **client_id = NULL;
1126 unsigned int client_id_count = 0;
1129 /* Parse the IDENTIFY request */
1130 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1131 &nick, &server_name, &count,
1132 SILC_COMMAND_IDENTIFY))
1135 /* Process the command request. Let's search for the requested client and
1136 send reply to the requesting server. */
1138 if (client_id_count) {
1139 /* Check all Client ID's received in the command packet */
1140 for (i = 0; i < client_id_count; i++) {
1141 entry = silc_idlist_find_client_by_id(server->local_list,
1142 client_id[i], NULL);
1144 clients = silc_realloc(clients, sizeof(*clients) *
1145 (clients_count + 1));
1146 clients[clients_count++] = entry;
1150 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1154 clients = silc_idlist_get_clients_by_hash(server->local_list,
1155 nick, server->md5hash,
1159 /* If we are router we will check our global list as well. */
1160 if (!clients && server->server_type == SILC_ROUTER) {
1161 if (client_id_count) {
1162 /* Check all Client ID's received in the command packet */
1163 for (i = 0; i < client_id_count; i++) {
1164 entry = silc_idlist_find_client_by_id(server->global_list,
1165 client_id[i], NULL);
1167 clients = silc_realloc(clients, sizeof(*clients) *
1168 (clients_count + 1));
1169 clients[clients_count++] = entry;
1173 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1177 clients = silc_idlist_get_clients_by_hash(server->global_list,
1178 nick, server->md5hash,
1184 /* Such a client really does not exist in the SILC network. */
1185 if (!client_id_count) {
1186 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1187 SILC_STATUS_ERR_NO_SUCH_NICK,
1188 3, nick, strlen(nick));
1190 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1191 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1192 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1193 2, idp->data, idp->len);
1194 silc_buffer_free(idp);
1199 /* Check that all mandatory fields are present and request those data
1200 from the server who owns the client if necessary. */
1201 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1206 /* Send the command reply */
1207 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1210 if (client_id_count) {
1211 for (i = 0; i < client_id_count; i++)
1212 silc_free(client_id[i]);
1213 silc_free(client_id);
1220 silc_free(server_name);
1225 SILC_SERVER_CMD_FUNC(identify)
1227 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1230 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1232 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1233 ret = silc_server_command_identify_from_client(cmd);
1234 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1235 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1236 ret = silc_server_command_identify_from_server(cmd);
1239 silc_server_command_free(cmd);
1242 /* Checks string for bad characters and returns TRUE if they are found. */
1244 static int silc_server_command_bad_chars(char *nick)
1246 if (strchr(nick, '\\')) return TRUE;
1247 if (strchr(nick, '\"')) return TRUE;
1248 if (strchr(nick, '´')) return TRUE;
1249 if (strchr(nick, '`')) return TRUE;
1250 if (strchr(nick, '\'')) return TRUE;
1251 if (strchr(nick, '*')) return TRUE;
1252 if (strchr(nick, '/')) return TRUE;
1253 if (strchr(nick, '@')) return TRUE;
1258 /* Server side of command NICK. Sets nickname for user. Setting
1259 nickname causes generation of a new client ID for the client. The
1260 new client ID is sent to the client after changing the nickname. */
1262 SILC_SERVER_CMD_FUNC(nick)
1264 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1265 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1266 SilcServer server = cmd->server;
1267 SilcBuffer packet, nidp, oidp;
1268 SilcClientID *new_id;
1271 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1273 /* Check nickname */
1274 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1275 if (silc_server_command_bad_chars(nick) == TRUE) {
1276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1277 SILC_STATUS_ERR_BAD_NICKNAME);
1281 /* Create new Client ID */
1282 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1283 cmd->server->md5hash, nick,
1286 /* Send notify about nickname change to our router. We send the new
1287 ID and ask to replace it with the old one. If we are router the
1288 packet is broadcasted. */
1289 if (!server->standalone)
1290 silc_server_send_replace_id(server, server->router->connection,
1291 server->server_type == SILC_SERVER ?
1292 FALSE : TRUE, client->id,
1293 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1294 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1296 /* Remove old cache entry */
1297 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1300 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1304 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1305 silc_free(client->id);
1308 /* Save the nickname as this client is our local client */
1309 if (client->nickname)
1310 silc_free(client->nickname);
1312 client->nickname = strdup(nick);
1313 client->id = new_id;
1315 /* Update client cache */
1316 silc_idcache_add(server->local_list->clients, client->nickname,
1317 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1319 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1321 /* Send NICK_CHANGE notify */
1322 silc_server_send_notify_on_channels(server, client,
1323 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1324 oidp->data, oidp->len,
1325 nidp->data, nidp->len);
1327 /* Send the new Client ID as reply command back to client */
1328 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1329 SILC_STATUS_OK, 0, 1,
1330 2, nidp->data, nidp->len);
1331 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1332 0, packet->data, packet->len, FALSE);
1334 silc_buffer_free(packet);
1335 silc_buffer_free(nidp);
1336 silc_buffer_free(oidp);
1339 silc_server_command_free(cmd);
1342 SILC_SERVER_CMD_FUNC(list)
1346 /* Server side of TOPIC command. Sets topic for channel and/or returns
1347 current topic to client. */
1349 SILC_SERVER_CMD_FUNC(topic)
1351 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1352 SilcServer server = cmd->server;
1353 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1354 SilcChannelID *channel_id;
1355 SilcChannelEntry channel;
1356 SilcChannelClientEntry chl;
1357 SilcBuffer packet, idp;
1359 unsigned int argc, tmp_len;
1361 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1363 argc = silc_argument_get_arg_num(cmd->args);
1365 /* Get Channel ID */
1366 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1369 SILC_STATUS_ERR_NO_CHANNEL_ID);
1372 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1375 SILC_STATUS_ERR_NO_CHANNEL_ID);
1379 /* Check whether the channel exists */
1380 channel = silc_idlist_find_channel_by_id(server->local_list,
1383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1384 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1390 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1393 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1397 if (strlen(tmp) > 256) {
1398 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1399 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1403 /* See whether has rights to change topic */
1404 silc_list_start(channel->user_list);
1405 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1406 if (chl->client == client)
1409 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1410 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1411 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1412 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1417 /* Set the topic for channel */
1419 silc_free(channel->topic);
1420 channel->topic = strdup(tmp);
1422 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1424 /* Send notify about topic change to all clients on the channel */
1425 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1426 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1427 idp->data, idp->len,
1428 channel->topic, strlen(channel->topic));
1429 silc_buffer_free(idp);
1432 /* Send the topic to client as reply packet */
1433 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1435 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1436 SILC_STATUS_OK, 0, 2,
1437 2, idp->data, idp->len,
1439 strlen(channel->topic));
1441 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1442 SILC_STATUS_OK, 0, 1,
1443 2, idp->data, idp->len);
1444 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1445 0, packet->data, packet->len, FALSE);
1447 silc_buffer_free(packet);
1448 silc_buffer_free(idp);
1449 silc_free(channel_id);
1452 silc_server_command_free(cmd);
1455 /* Server side of INVITE command. Invites some client to join some channel. */
1457 SILC_SERVER_CMD_FUNC(invite)
1459 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1460 SilcServer server = cmd->server;
1461 SilcSocketConnection sock = cmd->sock, dest_sock;
1462 SilcClientEntry sender, dest;
1463 SilcClientID *dest_id;
1464 SilcChannelEntry channel;
1465 SilcChannelID *channel_id;
1470 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1472 /* Get destination ID */
1473 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1475 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1476 SILC_STATUS_ERR_NO_CLIENT_ID);
1479 dest_id = silc_id_payload_parse_id(tmp, len);
1481 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1482 SILC_STATUS_ERR_NO_CLIENT_ID);
1486 /* Get Channel ID */
1487 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1489 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1490 SILC_STATUS_ERR_NO_CHANNEL_ID);
1493 channel_id = silc_id_payload_parse_id(tmp, len);
1495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1496 SILC_STATUS_ERR_NO_CHANNEL_ID);
1500 /* Check whether the channel exists */
1501 channel = silc_idlist_find_channel_by_id(server->local_list,
1504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1505 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1509 /* Check whether the sender of this command is on the channel. */
1510 sender = (SilcClientEntry)sock->user_data;
1511 if (!silc_server_client_on_channel(sender, channel)) {
1512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1513 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1517 /* Check whether the channel is invite-only channel. If yes then the
1518 sender of this command must be at least channel operator. */
1519 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1520 SilcChannelClientEntry chl;
1522 silc_list_start(channel->user_list);
1523 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1524 if (chl->client == sender) {
1525 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1527 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1534 /* Find the connection data for the destination. If it is local we will
1535 send it directly otherwise we will send it to router for routing. */
1536 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1538 dest_sock = (SilcSocketConnection)dest->connection;
1540 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1542 /* Check whether the requested client is already on the channel. */
1543 /* XXX if we are normal server we don't know about global clients on
1544 the channel thus we must request it (USERS command), check from
1545 local cache as well. */
1546 if (silc_server_client_on_channel(dest, channel)) {
1547 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1548 SILC_STATUS_ERR_USER_ON_CHANNEL);
1552 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1554 /* Send notify to the client that is invited to the channel */
1555 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1556 SILC_NOTIFY_TYPE_INVITE, 2,
1557 sidp->data, sidp->len, tmp, len);
1559 /* Send command reply */
1560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1563 silc_buffer_free(sidp);
1566 silc_server_command_free(cmd);
1569 /* Quits connection to client. This gets called if client won't
1570 close the connection even when it has issued QUIT command. */
1572 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1574 SilcServer server = (SilcServer)context;
1575 SilcSocketConnection sock = server->sockets[fd];
1577 /* Free all client specific data, such as client entry and entires
1578 on channels this client may be on. */
1579 silc_server_free_sock_user_data(server, sock);
1581 /* Close the connection on our side */
1582 silc_server_close_connection(server, sock);
1585 /* Quits SILC session. This is the normal way to disconnect client. */
1587 SILC_SERVER_CMD_FUNC(quit)
1589 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1590 SilcServer server = cmd->server;
1591 SilcSocketConnection sock = cmd->sock;
1593 SILC_LOG_DEBUG(("Start"));
1595 /* We quit the connection with little timeout */
1596 silc_task_register(server->timeout_queue, sock->sock,
1597 silc_server_command_quit_cb, server,
1598 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1600 silc_server_command_free(cmd);
1603 SILC_SERVER_CMD_FUNC(kill)
1607 /* Server side of command INFO. This sends information about us to
1608 the client. If client requested specific server we will send the
1609 command to that server. */
1611 SILC_SERVER_CMD_FUNC(info)
1613 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1614 SilcServer server = cmd->server;
1615 SilcBuffer packet, idp;
1616 char info_string[256], *dest_server;
1618 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1620 /* Get server name */
1621 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1623 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1624 SILC_STATUS_ERR_NO_SUCH_SERVER);
1628 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1629 /* Send our reply */
1630 memset(info_string, 0, sizeof(info_string));
1631 snprintf(info_string, sizeof(info_string),
1632 "location: %s server: %s admin: %s <%s>",
1633 server->config->admin_info->location,
1634 server->config->admin_info->server_type,
1635 server->config->admin_info->admin_name,
1636 server->config->admin_info->admin_email);
1638 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1640 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1641 SILC_STATUS_OK, 0, 2,
1642 2, idp->data, idp->len,
1644 strlen(info_string));
1645 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1646 packet->data, packet->len, FALSE);
1648 silc_buffer_free(packet);
1649 silc_buffer_free(idp);
1651 /* Send this command to the requested server */
1653 if (server->server_type == SILC_SERVER && !server->standalone) {
1657 if (server->server_type == SILC_ROUTER) {
1663 silc_server_command_free(cmd);
1666 SILC_SERVER_CMD_FUNC(connect)
1670 /* Server side of command PING. This just replies to the ping. */
1672 SILC_SERVER_CMD_FUNC(ping)
1674 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1675 SilcServer server = cmd->server;
1680 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1683 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1685 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1686 SILC_STATUS_ERR_NO_SERVER_ID);
1689 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1693 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1694 /* Send our reply */
1695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1699 SILC_STATUS_ERR_NO_SUCH_SERVER);
1706 silc_server_command_free(cmd);
1709 SILC_SERVER_CMD_FUNC(oper)
1713 /* Assembles USERS command and executes it. This is called when client
1714 joins to a channel and we wan't to send USERS command reply to the
1717 void silc_server_command_send_users(SilcServer server,
1718 SilcSocketConnection sock,
1719 SilcChannelEntry channel,
1722 SilcServerCommandContext cmd;
1723 SilcBuffer buffer, idp;
1724 SilcPacketContext *packet = silc_packet_context_alloc();
1726 SILC_LOG_DEBUG(("Start"));
1728 /* Create USERS command packet and process it. */
1729 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1730 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1731 1, idp->data, idp->len);
1733 packet->buffer = silc_buffer_copy(buffer);
1734 packet->sock = sock;
1735 packet->type = SILC_PACKET_COMMAND;
1737 cmd = silc_server_command_alloc();
1738 cmd->payload = silc_command_payload_parse(buffer);
1739 if (!cmd->payload) {
1741 silc_buffer_free(buffer);
1742 silc_buffer_free(idp);
1743 silc_packet_context_free(packet);
1746 cmd->args = silc_command_get_args(cmd->payload);
1747 cmd->server = server;
1748 cmd->sock = silc_socket_dup(sock);
1749 cmd->packet = silc_packet_context_dup(packet);
1750 cmd->pending = FALSE;
1753 /* If this function was called from pending command then instead of
1754 processing the command now, register a pending command callback which
1755 will process it after we've received the automatic USERS command
1756 reply which server will send in JOIN. */
1757 silc_server_command_pending(server, SILC_COMMAND_USERS, 0, NULL,
1758 silc_server_command_users, cmd);
1759 cmd->pending = TRUE;
1760 silc_buffer_free(buffer);
1761 silc_buffer_free(idp);
1765 /* Process USERS command. */
1766 silc_server_command_users((void *)cmd);
1768 silc_buffer_free(buffer);
1769 silc_buffer_free(idp);
1770 silc_packet_context_free(packet);
1773 /* Internal routine to join channel. The channel sent to this function
1774 has been either created or resolved from ID lists. This joins the sent
1775 client to the channel. */
1777 static void silc_server_command_join_channel(SilcServer server,
1778 SilcServerCommandContext cmd,
1779 SilcChannelEntry channel,
1780 SilcClientID *client_id,
1784 SilcSocketConnection sock = cmd->sock;
1786 unsigned int tmp_len;
1787 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1788 SilcClientEntry client;
1789 SilcChannelClientEntry chl;
1790 SilcBuffer reply, chidp, clidp, keyp;
1791 unsigned short ident = silc_command_get_ident(cmd->payload);
1793 SILC_LOG_DEBUG(("Start"));
1798 /* Get passphrase */
1799 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1801 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1802 memcpy(passphrase, tmp, tmp_len);
1806 * Check channel modes
1809 /* Check invite list if channel is invite-only channel */
1810 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1811 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1812 /* Invite list is specified. Check whether client is invited in the
1813 list. If not, then check whether it has been invited otherwise. */
1816 /* XXX client must be invited to be able to join the channel */
1820 /* Check ban list if set */
1821 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1825 /* Check the channel passphrase if set. */
1826 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1827 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1828 strlen(channel->mode_data.passphrase))) {
1829 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1830 SILC_STATUS_ERR_BAD_PASSWORD);
1835 /* Check user count limit if set. */
1836 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1837 if (silc_list_count(channel->user_list) + 1 >
1838 channel->mode_data.user_limit) {
1839 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1840 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1846 * Client is allowed to join to the channel. Make it happen.
1849 /* Get the client entry */
1850 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1851 client = (SilcClientEntry)sock->user_data;
1853 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1856 /* XXX actually this is useless since router finds always cell's
1857 local clients from its local lists. */
1858 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1865 /* Check whether the client already is on the channel */
1866 if (silc_server_client_on_channel(client, channel)) {
1867 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1868 SILC_STATUS_ERR_USER_ON_CHANNEL);
1872 /* Generate new channel key as protocol dictates */
1873 if (!created || !channel->channel_key)
1874 silc_server_create_channel_key(server, channel, 0);
1876 /* Send the channel key. This is broadcasted to the channel but is not
1877 sent to the client who is joining to the channel. */
1878 silc_server_send_channel_key(server, NULL, channel,
1879 server->server_type == SILC_ROUTER ?
1880 FALSE : server->standalone);
1882 /* Join the client to the channel by adding it to channel's user list.
1883 Add also the channel to client entry's channels list for fast cross-
1885 chl = silc_calloc(1, sizeof(*chl));
1887 chl->client = client;
1888 chl->channel = channel;
1889 silc_list_add(channel->user_list, chl);
1890 silc_list_add(client->channels, chl);
1892 /* Encode Client ID Payload of the original client who wants to join */
1893 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1895 /* Encode command reply packet */
1896 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1897 SILC_PUT32_MSB(channel->mode, mode);
1898 SILC_PUT32_MSB(created, tmp2);
1899 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1900 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1901 SILC_ID_CHANNEL_LEN,
1902 channel->channel_key->cipher->name,
1903 channel->key_len / 8, channel->key);
1905 if (!channel->topic) {
1907 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1908 SILC_STATUS_OK, ident, 5,
1909 2, channel->channel_name,
1910 strlen(channel->channel_name),
1911 3, chidp->data, chidp->len,
1914 6, keyp->data, keyp->len);
1917 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1918 SILC_STATUS_OK, ident, 6,
1919 2, channel->channel_name,
1920 strlen(channel->channel_name),
1921 3, chidp->data, chidp->len,
1924 6, keyp->data, keyp->len,
1926 strlen(channel->topic));
1929 /* Send command reply */
1930 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1931 reply->data, reply->len, FALSE);
1933 if (!cmd->pending) {
1934 /* Send JOIN notify to locally connected clients on the channel */
1935 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1936 SILC_NOTIFY_TYPE_JOIN, 1,
1937 clidp->data, clidp->len);
1939 /* Send NEW_CHANNEL_USER packet to our primary router */
1940 if (!server->standalone)
1941 silc_server_send_new_channel_user(server, server->router->connection,
1942 server->server_type == SILC_SERVER ?
1944 channel->id, SILC_ID_CHANNEL_LEN,
1945 client->id, SILC_ID_CLIENT_LEN);
1948 /* Send USERS command reply to the joined channel so the user sees who
1949 is currently on the channel. */
1950 silc_server_command_send_users(server, sock, channel, cmd->pending);
1952 silc_buffer_free(reply);
1953 silc_buffer_free(clidp);
1954 silc_buffer_free(chidp);
1955 silc_buffer_free(keyp);
1959 silc_free(passphrase);
1962 /* Server side of command JOIN. Joins client into requested channel. If
1963 the channel does not exist it will be created. */
1965 SILC_SERVER_CMD_FUNC(join)
1967 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1968 SilcServer server = cmd->server;
1970 char *tmp, *channel_name = NULL, *cipher = NULL;
1971 SilcChannelEntry channel;
1972 unsigned int umode = 0;
1973 int created = FALSE;
1974 SilcClientID *client_id;
1976 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1978 /* Get channel name */
1979 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1982 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1987 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1988 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1989 SILC_STATUS_ERR_BAD_CHANNEL);
1990 silc_free(channel_name);
1994 /* Get Client ID of the client who is joining to the channel */
1995 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1998 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2001 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2003 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2004 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2008 /* Get cipher name */
2009 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2011 /* See if the channel exists */
2012 channel = silc_idlist_find_channel_by_name(server->local_list,
2013 channel_name, NULL);
2015 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2016 /* If this is coming from client the Client ID in the command packet must
2017 be same as the client's ID. */
2018 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2019 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2020 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2021 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2022 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2028 /* Channel not found */
2030 /* If we are standalone server we don't have a router, we just create
2031 the channel by ourselves. */
2032 if (server->standalone) {
2033 channel = silc_server_create_new_channel(server, server->id, cipher,
2034 channel_name, TRUE);
2035 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2040 /* The channel does not exist on our server. If we are normal server
2041 we will send JOIN command to our router which will handle the
2042 joining procedure (either creates the channel if it doesn't exist
2043 or joins the client to it). */
2044 if (server->server_type == SILC_SERVER) {
2046 unsigned short old_ident;
2048 old_ident = silc_command_get_ident(cmd->payload);
2049 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2050 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2052 /* Send JOIN command to our router */
2053 silc_server_packet_send(server, (SilcSocketConnection)
2054 server->router->connection,
2055 SILC_PACKET_COMMAND, cmd->packet->flags,
2056 tmpbuf->data, tmpbuf->len, TRUE);
2058 /* Reprocess this packet after received reply from router */
2059 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2060 silc_command_get_ident(cmd->payload),
2061 silc_server_command_destructor,
2062 silc_server_command_join,
2063 silc_server_command_dup(cmd));
2064 cmd->pending = TRUE;
2068 /* We are router and the channel does not seem exist so we will check
2069 our global list as well for the channel. */
2070 channel = silc_idlist_find_channel_by_name(server->global_list,
2071 channel_name, NULL);
2073 /* Channel really does not exist, create it */
2074 channel = silc_server_create_new_channel(server, server->id, cipher,
2075 channel_name, TRUE);
2076 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2083 /* Channel not found */
2085 /* If the command came from router and/or we are normal server then
2086 something went wrong with the joining as the channel was not found.
2087 We can't do anything else but ignore this. */
2088 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2089 server->server_type == SILC_SERVER)
2092 /* We are router and the channel does not seem exist so we will check
2093 our global list as well for the channel. */
2094 channel = silc_idlist_find_channel_by_name(server->global_list,
2095 channel_name, NULL);
2097 /* Channel really does not exist, create it */
2098 channel = silc_server_create_new_channel(server, server->id, cipher,
2099 channel_name, TRUE);
2100 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2106 /* If the channel does not have global users and is also empty it means the
2107 channel was created globally (by our router) and the client will be the
2108 channel founder and operator. */
2109 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2110 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2111 created = TRUE; /* Created globally by our router */
2114 /* Join to the channel */
2115 silc_server_command_join_channel(server, cmd, channel, client_id,
2118 silc_free(client_id);
2121 silc_server_command_free(cmd);
2124 /* Server side of command MOTD. Sends server's current "message of the
2125 day" to the client. */
2127 SILC_SERVER_CMD_FUNC(motd)
2129 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2130 SilcServer server = cmd->server;
2134 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2136 /* XXX show currently only our motd */
2138 if (server->config && server->config->motd &&
2139 server->config->motd->motd_file) {
2142 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2147 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2153 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2158 silc_server_command_free(cmd);
2161 SILC_SERVER_CMD_FUNC(umode)
2165 /* Checks that client has rights to add or remove channel modes. If any
2166 of the checks fails FALSE is returned. */
2168 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2169 SilcChannelClientEntry client,
2172 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2173 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2175 /* Check whether has rights to change anything */
2176 if (!is_op && !is_fo)
2179 /* Check whether has rights to change everything */
2183 /* We know that client is channel operator, check that they are not
2184 changing anything that requires channel founder rights. Rest of the
2185 modes are available automatically for channel operator. */
2187 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2188 if (is_op && !is_fo)
2191 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2192 if (is_op && !is_fo)
2197 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2198 if (is_op && !is_fo)
2201 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2202 if (is_op && !is_fo)
2207 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2208 if (is_op && !is_fo)
2211 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2212 if (is_op && !is_fo)
2220 /* Server side command of CMODE. Changes channel mode */
2222 SILC_SERVER_CMD_FUNC(cmode)
2224 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2225 SilcServer server = cmd->server;
2226 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2227 SilcChannelID *channel_id;
2228 SilcChannelEntry channel;
2229 SilcChannelClientEntry chl;
2230 SilcBuffer packet, cidp;
2231 unsigned char *tmp, *tmp_id, *tmp_mask;
2232 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2234 SILC_LOG_DEBUG(("Start"));
2236 argc = silc_argument_get_arg_num(cmd->args);
2238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2239 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2244 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2248 /* Get Channel ID */
2249 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2251 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2252 SILC_STATUS_ERR_NO_CHANNEL_ID);
2255 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2257 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2258 SILC_STATUS_ERR_NO_CHANNEL_ID);
2262 /* Get the channel mode mask */
2263 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2266 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2269 SILC_GET32_MSB(mode_mask, tmp_mask);
2271 /* Get channel entry */
2272 channel = silc_idlist_find_channel_by_id(server->local_list,
2275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2276 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2280 /* Check whether this client is on the channel */
2281 if (!silc_server_client_on_channel(client, channel)) {
2282 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2283 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2287 /* Get entry to the channel user list */
2288 silc_list_start(channel->user_list);
2289 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2290 if (chl->client == client)
2293 /* Check that client has rights to change any requested channel modes */
2294 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2296 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2301 * Check the modes. Modes that requires nothing special operation are
2305 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2306 /* Channel uses private keys to protect traffic. Client(s) has set the
2307 key locally they want to use, server does not know that key. */
2308 /* Nothing interesting to do here now */
2310 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2311 /* The mode is removed and we need to generate and distribute
2312 new channel key. Clients are not using private channel keys
2313 anymore after this. */
2315 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2318 /* Re-generate channel key */
2319 silc_server_create_channel_key(server, channel, 0);
2321 /* Encode channel key payload to be distributed on the channel */
2323 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2324 strlen(channel->channel_key->
2326 channel->channel_key->cipher->name,
2327 channel->key_len / 8, channel->key);
2329 /* If we are normal server then we will send it to our router. If we
2330 are router we will send it to all local servers that has clients on
2332 if (server->server_type == SILC_SERVER) {
2333 if (!server->standalone)
2334 silc_server_packet_send(server,
2335 cmd->server->router->connection,
2336 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2342 /* Send to locally connected clients on the channel */
2343 silc_server_packet_send_local_channel(server, channel,
2344 SILC_PACKET_CHANNEL_KEY, 0,
2345 packet->data, packet->len, FALSE);
2346 silc_buffer_free(packet);
2350 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2351 /* User limit is set on channel */
2352 unsigned int user_limit;
2354 /* Get user limit */
2355 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2357 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2358 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2359 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2363 SILC_GET32_MSB(user_limit, tmp);
2364 channel->mode_data.user_limit = user_limit;
2367 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2368 /* User limit mode is unset. Remove user limit */
2369 channel->mode_data.user_limit = 0;
2372 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2373 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2374 /* Passphrase has been set to channel */
2376 /* Get the passphrase */
2377 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2379 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2380 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2384 /* Save the passphrase */
2385 channel->mode_data.passphrase = strdup(tmp);
2388 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2389 /* Passphrase mode is unset. remove the passphrase */
2390 if (channel->mode_data.passphrase) {
2391 silc_free(channel->mode_data.passphrase);
2392 channel->mode_data.passphrase = NULL;
2397 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2398 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2399 /* Ban list is specified for channel */
2402 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2404 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2405 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2409 /* XXX check that channel founder is not banned */
2411 /* Save the ban list */
2412 channel->mode_data.ban_list = strdup(tmp);
2415 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2416 /* Ban mode is unset. Remove the entire ban list */
2417 if (channel->mode_data.ban_list) {
2418 silc_free(channel->mode_data.ban_list);
2419 channel->mode_data.ban_list = NULL;
2424 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2425 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2426 /* Invite list is specified for channel */
2428 /* Get invite list */
2429 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2431 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2432 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2436 /* Save the invite linst */
2437 channel->mode_data.invite_list = strdup(tmp);
2440 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2441 /* Invite list mode is unset. Remove the entire invite list */
2442 if (channel->mode_data.invite_list) {
2443 silc_free(channel->mode_data.invite_list);
2444 channel->mode_data.invite_list = NULL;
2449 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2450 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2451 /* Cipher to use protect the traffic */
2452 unsigned int key_len = 128;
2456 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2458 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2459 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2463 cp = strchr(tmp, ':');
2469 /* XXX Duplicated code, make own function for this!! */
2471 /* Delete old cipher and allocate the new one */
2472 silc_cipher_free(channel->channel_key);
2473 silc_cipher_alloc(tmp, &channel->channel_key);
2479 /* Re-generate channel key */
2480 silc_server_create_channel_key(server, channel, key_len);
2482 /* Encode channel key payload to be distributed on the channel */
2484 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2485 strlen(channel->channel_key->
2487 channel->channel_key->cipher->name,
2488 channel->key_len / 8, channel->key);
2490 /* If we are normal server then we will send it to our router. If we
2491 are router we will send it to all local servers that has clients on
2493 if (server->server_type == SILC_SERVER) {
2494 if (!server->standalone)
2495 silc_server_packet_send(server,
2496 cmd->server->router->connection,
2497 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2503 /* Send to locally connected clients on the channel */
2504 silc_server_packet_send_local_channel(server, channel,
2505 SILC_PACKET_CHANNEL_KEY, 0,
2506 packet->data, packet->len, FALSE);
2507 silc_buffer_free(packet);
2510 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2511 /* Cipher mode is unset. Remove the cipher and revert back to
2514 if (channel->mode_data.cipher) {
2515 silc_free(channel->mode_data.cipher);
2516 channel->mode_data.cipher = NULL;
2517 channel->mode_data.key_len = 0;
2520 /* Generate new cipher and key for the channel */
2522 /* XXX Duplicated code, make own function for this!! */
2524 /* Delete old cipher and allocate default one */
2525 silc_cipher_free(channel->channel_key);
2526 if (!channel->cipher)
2527 silc_cipher_alloc("twofish", &channel->channel_key);
2529 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2531 /* Re-generate channel key */
2532 silc_server_create_channel_key(server, channel, 0);
2534 /* Encode channel key payload to be distributed on the channel */
2536 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2537 strlen(channel->channel_key->
2539 channel->channel_key->cipher->name,
2540 channel->key_len / 8, channel->key);
2542 /* If we are normal server then we will send it to our router. If we
2543 are router we will send it to all local servers that has clients on
2545 if (server->server_type == SILC_SERVER) {
2546 if (!server->standalone)
2547 silc_server_packet_send(server,
2548 cmd->server->router->connection,
2549 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2555 /* Send to locally connected clients on the channel */
2556 silc_server_packet_send_local_channel(server, channel,
2557 SILC_PACKET_CHANNEL_KEY, 0,
2558 packet->data, packet->len, FALSE);
2559 silc_buffer_free(packet);
2563 /* Finally, set the mode */
2564 channel->mode = mode_mask;
2566 /* Send CMODE_CHANGE notify */
2567 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2568 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2569 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2570 cidp->data, cidp->len,
2573 /* Set SET_MODE packet to network */
2574 if (!server->standalone)
2575 silc_server_send_set_mode(server, server->router->connection,
2576 server->server_type == SILC_ROUTER ?
2577 TRUE : FALSE, SILC_MODE_TYPE_CHANNEL,
2580 cidp->data, cidp->len);
2582 /* Send command reply to sender */
2583 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2584 SILC_STATUS_OK, 0, 1,
2586 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2587 packet->data, packet->len, FALSE);
2589 silc_buffer_free(packet);
2590 silc_free(channel_id);
2594 silc_server_command_free(cmd);
2597 /* Server side of CUMODE command. Changes client's mode on a channel. */
2599 SILC_SERVER_CMD_FUNC(cumode)
2601 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2602 SilcServer server = cmd->server;
2603 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2604 SilcChannelID *channel_id;
2605 SilcClientID *client_id;
2606 SilcChannelEntry channel;
2607 SilcClientEntry target_client;
2608 SilcChannelClientEntry chl;
2609 SilcBuffer packet, idp;
2610 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2611 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
2614 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2616 /* Get Channel ID */
2617 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2619 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2620 SILC_STATUS_ERR_NO_CHANNEL_ID);
2623 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
2625 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2626 SILC_STATUS_ERR_NO_CHANNEL_ID);
2630 /* Get channel entry */
2631 channel = silc_idlist_find_channel_by_id(server->local_list,
2634 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2635 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2639 /* Check whether sender is on the channel */
2640 if (!silc_server_client_on_channel(client, channel)) {
2641 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2642 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2646 /* Check that client has rights to change other's rights */
2647 silc_list_start(channel->user_list);
2648 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2649 if (chl->client == client) {
2650 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2651 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2653 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2657 sender_mask = chl->mode;
2662 /* Get the target client's channel mode mask */
2663 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2665 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2666 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2669 SILC_GET32_MSB(target_mask, tmp_mask);
2671 /* Get target Client ID */
2672 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2675 SILC_STATUS_ERR_NO_CHANNEL_ID);
2678 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2681 SILC_STATUS_ERR_NO_CHANNEL_ID);
2685 /* Get target client's entry */
2686 target_client = silc_idlist_find_client_by_id(server->local_list,
2688 if (!target_client) {
2689 target_client = silc_idlist_find_client_by_id(server->global_list,
2693 /* Check whether target client is on the channel */
2694 if (!silc_server_client_on_channel(target_client, channel)) {
2695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2696 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2700 /* Get entry to the channel user list */
2701 silc_list_start(channel->user_list);
2702 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2703 if (chl->client == target_client)
2710 /* If the target client is founder, no one else can change their mode
2712 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2713 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2714 SILC_STATUS_ERR_NOT_YOU);
2718 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2719 /* Cannot promote anyone to channel founder */
2720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2721 SILC_STATUS_ERR_NOT_YOU);
2724 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2725 if (target_client == client) {
2726 /* Remove channel founder rights from itself */
2727 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2730 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2731 SILC_STATUS_ERR_NOT_YOU);
2737 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2738 /* Promote to operator */
2739 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2740 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2744 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2745 /* Demote to normal user */
2746 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2751 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2753 /* Send notify to channel, notify only if mode was actually changed. */
2755 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2756 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2757 idp->data, idp->len,
2762 /* Set SET_MODE packet to network */
2763 if (!server->standalone)
2764 silc_server_send_set_mode(server, server->router->connection,
2765 server->server_type == SILC_ROUTER ?
2766 TRUE : FALSE, SILC_MODE_TYPE_UCHANNEL,
2768 tmp_ch_id, tmp_ch_len,
2769 idp->data, idp->len,
2772 /* Send command reply to sender */
2773 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2774 SILC_STATUS_OK, 0, 2,
2776 3, tmp_id, tmp_len);
2777 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2778 packet->data, packet->len, FALSE);
2780 silc_buffer_free(packet);
2781 silc_free(channel_id);
2782 silc_free(client_id);
2783 silc_buffer_free(idp);
2786 silc_server_command_free(cmd);
2789 /* Server side of KICK command. Kicks client out of channel. */
2791 SILC_SERVER_CMD_FUNC(kick)
2795 SILC_SERVER_CMD_FUNC(restart)
2799 SILC_SERVER_CMD_FUNC(close)
2803 SILC_SERVER_CMD_FUNC(die)
2807 SILC_SERVER_CMD_FUNC(silcoper)
2811 /* Server side command of LEAVE. Removes client from a channel. */
2813 SILC_SERVER_CMD_FUNC(leave)
2815 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2816 SilcServer server = cmd->server;
2817 SilcSocketConnection sock = cmd->sock;
2818 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2820 SilcChannelEntry channel;
2822 unsigned int i, len;
2825 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2827 /* Get Channel ID */
2828 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2830 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2831 SILC_STATUS_ERR_NO_CHANNEL_ID);
2834 id = silc_id_payload_parse_id(tmp, len);
2836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2837 SILC_STATUS_ERR_NO_CHANNEL_ID);
2841 /* Get channel entry */
2842 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2844 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2845 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2849 /* Check whether this client is on the channel */
2850 if (!silc_server_client_on_channel(id_entry, channel)) {
2851 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2852 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2856 /* Notify routers that they should remove this client from their list
2857 of clients on the channel. */
2858 if (!server->standalone)
2859 silc_server_send_remove_channel_user(server,
2860 server->router->connection,
2861 server->server_type == SILC_ROUTER ?
2862 TRUE : FALSE, id_entry->id, id);
2864 /* Remove client from channel */
2865 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2867 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2870 /* If the channel does not exist anymore we won't send anything */
2874 /* Re-generate channel key */
2875 silc_server_create_channel_key(server, channel, 0);
2877 /* Encode channel key payload to be distributed on the channel */
2879 silc_channel_key_payload_encode(len, tmp,
2880 strlen(channel->channel_key->cipher->name),
2881 channel->channel_key->cipher->name,
2882 channel->key_len / 8, channel->key);
2884 /* If we are normal server then we will send it to our router. If we
2885 are router we will send it to all local servers that has clients on
2887 if (server->server_type == SILC_SERVER) {
2888 if (!server->standalone)
2889 silc_server_packet_send(server,
2890 cmd->server->router->connection,
2891 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2892 packet->len, FALSE);
2897 /* Send to locally connected clients on the channel */
2898 silc_server_packet_send_local_channel(server, channel,
2899 SILC_PACKET_CHANNEL_KEY, 0,
2900 packet->data, packet->len, FALSE);
2902 silc_buffer_free(packet);
2906 silc_server_command_free(cmd);
2909 /* Server side of command USERS. Resolves clients and their USERS currently
2910 joined on the requested channel. The list of Client ID's and their modes
2911 on the channel is sent back. */
2913 SILC_SERVER_CMD_FUNC(users)
2915 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2916 SilcServer server = cmd->server;
2917 SilcChannelEntry channel;
2918 SilcChannelClientEntry chl;
2921 unsigned char *channel_id;
2922 unsigned int channel_id_len;
2923 SilcBuffer client_id_list;
2924 SilcBuffer client_mode_list;
2926 unsigned char lc[4];
2927 unsigned int list_count = 0;
2928 unsigned short ident = silc_command_get_ident(cmd->payload);
2930 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
2932 /* Get Channel ID */
2933 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
2935 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2936 SILC_STATUS_ERR_NO_CHANNEL_ID);
2939 id = silc_id_payload_parse_id(channel_id, channel_id_len);
2941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2942 SILC_STATUS_ERR_NO_CHANNEL_ID);
2946 /* If we are server and we don't know about this channel we will send
2947 the command to our router. If we know about the channel then we also
2948 have the list of users already. */
2949 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2951 if (server->server_type == SILC_SERVER && !server->standalone &&
2955 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2956 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2958 /* Send USERS command */
2959 silc_server_packet_send(server, server->router->connection,
2960 SILC_PACKET_COMMAND, cmd->packet->flags,
2961 tmpbuf->data, tmpbuf->len, TRUE);
2963 /* Reprocess this packet after received reply */
2964 silc_server_command_pending(server, SILC_COMMAND_USERS,
2965 silc_command_get_ident(cmd->payload),
2966 silc_server_command_destructor,
2967 silc_server_command_users,
2968 silc_server_command_dup(cmd));
2969 cmd->pending = TRUE;
2970 silc_command_set_ident(cmd->payload, ident);
2972 silc_buffer_free(tmpbuf);
2977 /* We are router and we will check the global list as well. */
2978 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2980 /* Channel really does not exist */
2981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2982 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2987 /* Assemble the lists now */
2989 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2990 silc_list_count(channel->user_list));
2991 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2993 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2994 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2996 silc_list_start(channel->user_list);
2997 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2999 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
3000 silc_buffer_put(client_id_list, idp->data, idp->len);
3001 silc_buffer_pull(client_id_list, idp->len);
3002 silc_buffer_free(idp);
3004 /* Client's mode on channel */
3005 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
3006 silc_buffer_pull(client_mode_list, 4);
3010 silc_buffer_push(client_id_list,
3011 client_id_list->data - client_id_list->head);
3012 silc_buffer_push(client_mode_list,
3013 client_mode_list->data - client_mode_list->head);
3016 SILC_PUT32_MSB(list_count, lc);
3019 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3020 SILC_STATUS_OK, 0, 4,
3021 2, channel_id, channel_id_len,
3023 4, client_id_list->data,
3024 client_id_list->len,
3025 5, client_mode_list->data,
3026 client_mode_list->len);
3027 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3028 packet->data, packet->len, FALSE);
3030 silc_buffer_free(packet);
3031 silc_buffer_free(client_id_list);
3032 silc_buffer_free(client_mode_list);
3036 silc_server_command_free(cmd);