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);
41 /* Server command list. */
42 SilcServerCommand silc_command_list[] =
44 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
45 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
46 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
47 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
48 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
49 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
53 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
54 SILC_SERVER_CMD(connect, CONNECT,
55 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
56 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(restart, RESTART,
65 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
66 SILC_SERVER_CMD(close, CLOSE,
67 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
68 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
70 SILC_SERVER_CMD(silcoper, SILCOPER,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
72 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
73 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
78 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
80 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
82 SILC_LOG_DEBUG(("Start")); \
85 silc_server_command_send_status_reply(cmd, command, \
86 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
87 silc_server_command_free(cmd); \
91 silc_server_command_send_status_reply(cmd, command, \
92 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
93 silc_server_command_free(cmd); \
98 /* Returns TRUE if the connection is registered. Unregistered connections
99 usually cannot send commands hence the check. */
101 static int silc_server_is_registered(SilcServer server,
102 SilcSocketConnection sock,
103 SilcServerCommandContext cmd,
106 SilcIDListData idata = (SilcIDListData)sock->user_data;
107 if (idata->registered)
110 silc_server_command_send_status_reply(cmd, command,
111 SILC_STATUS_ERR_NOT_REGISTERED);
112 silc_server_command_free(cmd);
116 /* Processes received command packet. */
118 void silc_server_command_process(SilcServer server,
119 SilcSocketConnection sock,
120 SilcPacketContext *packet)
122 SilcServerCommandContext ctx;
123 SilcServerCommand *cmd;
126 /* XXX allow commands in but do not execute them more than once per
129 /* Check whether it is allowed for this connection to execute any
131 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
133 SilcClientEntry client = (SilcClientEntry)sock->user_data;
138 /* Allow only one command executed in 2 seconds. */
139 curtime = time(NULL);
140 if (client->last_command && (curtime - client->last_command) < 2)
143 /* Update access time */
144 client->last_command = curtime;
148 /* Allocate command context. This must be free'd by the
149 command routine receiving it. */
150 ctx = silc_server_command_alloc();
151 ctx->server = server;
152 ctx->sock = silc_socket_dup(sock);
153 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
155 /* Parse the command payload in the packet */
156 ctx->payload = silc_command_payload_parse(packet->buffer);
158 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
159 silc_buffer_free(packet->buffer);
160 silc_packet_context_free(packet);
161 silc_socket_free(ctx->sock);
165 ctx->args = silc_command_get_args(ctx->payload);
167 /* Execute command. If this fails the packet is dropped. */
168 for (cmd = silc_command_list; cmd->cb; cmd++)
169 if (cmd->cmd == silc_command_get(ctx->payload)) {
171 if (!(cmd->flags & SILC_CF_REG)) {
176 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
183 SILC_LOG_ERROR(("Unknown command, packet dropped"));
184 silc_server_command_free(ctx);
189 /* Allocate Command Context */
191 SilcServerCommandContext silc_server_command_alloc()
193 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
198 /* Free's the command context allocated before executing the command */
200 void silc_server_command_free(SilcServerCommandContext ctx)
203 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
205 if (ctx->users < 1) {
207 silc_command_free_payload(ctx->payload);
209 silc_packet_context_free(ctx->packet);
211 silc_socket_free(ctx->sock); /* Decrease reference counter */
216 /* Duplicate Command Context by adding reference counter. The context won't
217 be free'd untill it hits zero. */
219 SilcServerCommandContext
220 silc_server_command_dup(SilcServerCommandContext ctx)
223 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
228 /* Add new pending command to be executed when reply to a command has been
229 received. The `reply_cmd' is the command that will call the `callback'
230 with `context' when reply has been received. If `ident' is non-zero
231 the `callback' will be executed when received reply with command
232 identifier `ident'. */
234 void silc_server_command_pending(SilcServer server,
235 SilcCommand reply_cmd,
236 unsigned short ident,
237 SilcServerPendingDestructor destructor,
238 SilcCommandCb callback,
241 SilcServerCommandPending *reply;
243 reply = silc_calloc(1, sizeof(*reply));
244 reply->reply_cmd = reply_cmd;
245 reply->ident = ident;
246 reply->context = context;
247 reply->callback = callback;
248 reply->destructor = destructor;
249 silc_dlist_add(server->pending_commands, reply);
252 /* Deletes pending command by reply command type. */
254 void silc_server_command_pending_del(SilcServer server,
255 SilcCommand reply_cmd,
256 unsigned short ident)
258 SilcServerCommandPending *r;
260 silc_dlist_start(server->pending_commands);
261 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
262 if (r->reply_cmd == reply_cmd && r->ident == ident) {
263 silc_dlist_del(server->pending_commands, r);
269 /* Checks for pending commands and marks callbacks to be called from
270 the command reply function. Returns TRUE if there were pending command. */
272 int silc_server_command_pending_check(SilcServer server,
273 SilcServerCommandReplyContext ctx,
275 unsigned short ident)
277 SilcServerCommandPending *r;
279 silc_dlist_start(server->pending_commands);
280 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
281 if (r->reply_cmd == command && r->ident == ident) {
282 ctx->context = r->context;
283 ctx->callback = r->callback;
284 ctx->destructor = r->destructor;
293 /* Destructor function for pending callbacks. This is called when using
294 pending commands to free the context given for the pending command. */
296 static void silc_server_command_destructor(void *context)
298 silc_server_command_free((SilcServerCommandContext)context);
301 /* Sends simple status message as command reply packet */
304 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
306 SilcCommandStatus status)
310 SILC_LOG_DEBUG(("Sending command status %d", status));
312 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
313 silc_server_packet_send(cmd->server, cmd->sock,
314 SILC_PACKET_COMMAND_REPLY, 0,
315 buffer->data, buffer->len, FALSE);
316 silc_buffer_free(buffer);
319 /* Sends command status reply with one extra argument. The argument
320 type must be sent as argument. */
323 silc_server_command_send_status_data(SilcServerCommandContext cmd,
325 SilcCommandStatus status,
326 unsigned int arg_type,
328 unsigned int arg_len)
332 SILC_LOG_DEBUG(("Sending command status %d", status));
334 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
335 arg_type, arg, arg_len);
336 silc_server_packet_send(cmd->server, cmd->sock,
337 SILC_PACKET_COMMAND_REPLY, 0,
338 buffer->data, buffer->len, FALSE);
339 silc_buffer_free(buffer);
342 /******************************************************************************
346 ******************************************************************************/
349 silc_server_command_whois_parse(SilcServerCommandContext cmd,
350 SilcClientID ***client_id,
351 unsigned int *client_id_count,
359 unsigned int argc = silc_argument_get_arg_num(cmd->args);
362 /* If client ID is in the command it must be used instead of nickname */
363 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
365 /* No ID, get the nickname@server string and parse it. */
366 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
368 if (strchr(tmp, '@')) {
369 len = strcspn(tmp, "@");
370 *nickname = silc_calloc(len + 1, sizeof(char));
371 memcpy(*nickname, tmp, len);
372 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
373 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
375 *nickname = strdup(tmp);
378 silc_server_command_send_status_reply(cmd, command,
379 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
383 /* Command includes ID, we must use that. Also check whether the command
384 has more than one ID set - take them all. */
386 *client_id = silc_calloc(1, sizeof(**client_id));
387 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
388 if ((*client_id)[0] == NULL) {
389 silc_free(*client_id);
392 *client_id_count = 1;
394 /* Take all ID's from the command packet */
396 for (k = 1, i = 1; i < argc; i++) {
397 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
399 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
400 (*client_id_count + 1));
401 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
402 if ((*client_id)[k] == NULL) {
403 /* Cleanup all and fail */
404 for (i = 0; i < *client_id_count; i++)
405 silc_free((*client_id)[i]);
406 silc_free(*client_id);
409 (*client_id_count)++;
415 /* Command includes ID, use that */
418 /* Get the max count of reply messages allowed */
419 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
429 silc_server_command_whois_check(SilcServerCommandContext cmd,
430 SilcClientEntry *clients,
431 unsigned int clients_count)
433 SilcServer server = cmd->server;
435 SilcClientEntry entry;
437 for (i = 0; i < clients_count; i++) {
440 if (!entry->nickname || !entry->username) {
442 unsigned short old_ident;
447 old_ident = silc_command_get_ident(cmd->payload);
448 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
449 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
451 /* Send WHOIS command */
452 silc_server_packet_send(server, entry->router->connection,
453 SILC_PACKET_COMMAND, cmd->packet->flags,
454 tmpbuf->data, tmpbuf->len, TRUE);
456 /* Reprocess this packet after received reply */
457 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
458 silc_command_get_ident(cmd->payload),
459 silc_server_command_destructor,
460 silc_server_command_whois,
461 silc_server_command_dup(cmd));
464 silc_command_set_ident(cmd->payload, old_ident);
466 silc_buffer_free(tmpbuf);
475 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
476 SilcClientEntry *clients,
477 unsigned int clients_count)
479 SilcServer server = cmd->server;
481 int i, count = 0, len;
482 SilcBuffer packet, idp;
483 SilcClientEntry entry;
484 SilcCommandStatus status;
485 unsigned short ident = silc_command_get_ident(cmd->payload);
487 status = SILC_STATUS_OK;
488 if (clients_count > 1)
489 status = SILC_STATUS_LIST_START;
491 for (i = 0; i < clients_count; i++) {
494 if (count && i - 1 == count)
497 if (clients_count > 2)
498 status = SILC_STATUS_LIST_ITEM;
500 if (clients_count > 1 && i == clients_count - 1)
501 status = SILC_STATUS_LIST_END;
503 /* Sanity check, however these should never fail. However, as
504 this sanity check has been added here they have failed. */
505 if (!entry->nickname || !entry->username)
508 /* Send WHOIS reply */
509 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
510 tmp = silc_argument_get_first_arg(cmd->args, NULL);
514 char nh[256], uh[256];
515 unsigned char idle[4];
516 SilcSocketConnection hsock;
518 memset(uh, 0, sizeof(uh));
519 memset(nh, 0, sizeof(nh));
521 strncat(nh, entry->nickname, strlen(entry->nickname));
522 if (!strchr(entry->nickname, '@')) {
524 len = entry->router ? strlen(entry->router->server_name) :
525 strlen(server->server_name);
526 strncat(nh, entry->router ? entry->router->server_name :
527 server->server_name, len);
530 strncat(uh, entry->username, strlen(entry->username));
531 if (!strchr(entry->username, '@')) {
533 hsock = (SilcSocketConnection)entry->connection;
534 len = strlen(hsock->hostname);
535 strncat(uh, hsock->hostname, len);
538 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
541 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
543 2, idp->data, idp->len,
547 strlen(entry->userinfo),
551 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
552 0, packet->data, packet->len, FALSE);
554 silc_buffer_free(packet);
555 silc_buffer_free(idp);
560 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
562 SilcServer server = cmd->server;
563 char *nick = NULL, *server_name = NULL;
564 int count = 0, clients_count = 0;
565 SilcClientEntry *clients = NULL, entry;
566 SilcClientID **client_id = NULL;
567 unsigned int client_id_count = 0;
570 /* Protocol dictates that we must always send the received WHOIS request
571 to our router if we are normal server, so let's do it now unless we
572 are standalone. We will not send any replies to the client until we
573 have received reply from the router. */
574 if (server->server_type == SILC_SERVER &&
575 !cmd->pending && !server->standalone) {
577 unsigned short old_ident;
579 old_ident = silc_command_get_ident(cmd->payload);
580 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
581 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
583 /* Send WHOIS command to our router */
584 silc_server_packet_send(server, (SilcSocketConnection)
585 server->router->connection,
586 SILC_PACKET_COMMAND, cmd->packet->flags,
587 tmpbuf->data, tmpbuf->len, TRUE);
589 /* Reprocess this packet after received reply from router */
590 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
591 silc_command_get_ident(cmd->payload),
592 silc_server_command_destructor,
593 silc_server_command_whois,
594 silc_server_command_dup(cmd));
597 silc_command_set_ident(cmd->payload, old_ident);
599 silc_buffer_free(tmpbuf);
604 /* We are ready to process the command request. Let's search for the
605 requested client and send reply to the requesting client. */
607 /* Parse the whois request */
608 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
609 &nick, &server_name, &count,
613 /* Get all clients matching that ID or nickname from local list */
614 if (client_id_count) {
615 /* Check all Client ID's received in the command packet */
616 for (i = 0; i < client_id_count; i++) {
617 entry = silc_idlist_find_client_by_id(server->local_list,
620 clients = silc_realloc(clients, sizeof(*clients) *
621 (clients_count + 1));
622 clients[clients_count++] = entry;
626 clients = silc_idlist_get_clients_by_nickname(server->local_list,
630 clients = silc_idlist_get_clients_by_hash(server->local_list,
631 nick, server->md5hash,
635 /* Check global list as well */
637 if (client_id_count) {
638 /* Check all Client ID's received in the command packet */
639 for (i = 0; i < client_id_count; i++) {
640 entry = silc_idlist_find_client_by_id(server->global_list,
643 clients = silc_realloc(clients, sizeof(*clients) *
644 (clients_count + 1));
645 clients[clients_count++] = entry;
649 clients = silc_idlist_get_clients_by_nickname(server->global_list,
653 clients = silc_idlist_get_clients_by_hash(server->global_list,
654 nick, server->md5hash,
660 /* Such client(s) really does not exist in the SILC network. */
661 if (!client_id_count) {
662 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
663 SILC_STATUS_ERR_NO_SUCH_NICK,
664 3, nick, strlen(nick));
666 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
667 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
668 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
669 2, idp->data, idp->len);
670 silc_buffer_free(idp);
675 /* Router always finds the client entry if it exists in the SILC network.
676 However, it might be incomplete entry and does not include all the
677 mandatory fields that WHOIS command reply requires. Check for these and
678 make query from the server who owns the client if some fields are
680 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
685 /* Send the command reply to the client */
686 silc_server_command_whois_send_reply(cmd, clients, clients_count);
689 if (client_id_count) {
690 for (i = 0; i < client_id_count; i++)
691 silc_free(client_id[i]);
692 silc_free(client_id);
699 silc_free(server_name);
705 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
707 SilcServer server = cmd->server;
708 char *nick = NULL, *server_name = NULL;
709 int count = 0, clients_count = 0;
710 SilcClientEntry *clients = NULL, entry;
711 SilcClientID **client_id = NULL;
712 unsigned int client_id_count = 0;
715 /* Parse the whois request */
716 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
717 &nick, &server_name, &count,
721 /* Process the command request. Let's search for the requested client and
722 send reply to the requesting server. */
724 if (client_id_count) {
725 /* Check all Client ID's received in the command packet */
726 for (i = 0; i < client_id_count; i++) {
727 entry = silc_idlist_find_client_by_id(server->local_list,
730 clients = silc_realloc(clients, sizeof(*clients) *
731 (clients_count + 1));
732 clients[clients_count++] = entry;
736 clients = silc_idlist_get_clients_by_nickname(server->local_list,
740 clients = silc_idlist_get_clients_by_hash(server->local_list,
741 nick, server->md5hash,
745 /* If we are router we will check our global list as well. */
746 if (!clients && server->server_type == SILC_ROUTER) {
747 if (client_id_count) {
748 /* Check all Client ID's received in the command packet */
749 for (i = 0; i < client_id_count; i++) {
750 entry = silc_idlist_find_client_by_id(server->global_list,
753 clients = silc_realloc(clients, sizeof(*clients) *
754 (clients_count + 1));
755 clients[clients_count++] = entry;
759 clients = silc_idlist_get_clients_by_nickname(server->global_list,
763 clients = silc_idlist_get_clients_by_hash(server->global_list,
764 nick, server->md5hash,
770 /* Such a client really does not exist in the SILC network. */
771 if (!client_id_count) {
772 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
773 SILC_STATUS_ERR_NO_SUCH_NICK,
774 3, nick, strlen(nick));
776 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
777 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
778 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
779 2, idp->data, idp->len);
780 silc_buffer_free(idp);
785 /* Router always finds the client entry if it exists in the SILC network.
786 However, it might be incomplete entry and does not include all the
787 mandatory fields that WHOIS command reply requires. Check for these and
788 make query from the server who owns the client if some fields are
790 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
795 /* Send the command reply to the client */
796 silc_server_command_whois_send_reply(cmd, clients, clients_count);
799 if (client_id_count) {
800 for (i = 0; i < client_id_count; i++)
801 silc_free(client_id[i]);
802 silc_free(client_id);
809 silc_free(server_name);
814 /* Server side of command WHOIS. Processes user's query and sends found
815 results as command replies back to the client. */
817 SILC_SERVER_CMD_FUNC(whois)
819 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
822 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
824 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
825 ret = silc_server_command_whois_from_client(cmd);
826 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
827 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
828 ret = silc_server_command_whois_from_server(cmd);
831 silc_server_command_free(cmd);
834 SILC_SERVER_CMD_FUNC(whowas)
838 /******************************************************************************
842 ******************************************************************************/
844 /* Checks that all mandatory fields are present. If not then send WHOIS
845 request to the server who owns the client. We use WHOIS because we want
846 to get as much information as possible at once. */
849 silc_server_command_identify_check(SilcServerCommandContext cmd,
850 SilcClientEntry *clients,
851 unsigned int clients_count)
853 SilcServer server = cmd->server;
855 SilcClientEntry entry;
857 for (i = 0; i < clients_count; i++) {
860 if (!entry->nickname) {
862 unsigned short old_ident;
867 old_ident = silc_command_get_ident(cmd->payload);
868 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
869 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
870 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
872 /* Send WHOIS request. We send WHOIS since we're doing the requesting
873 now anyway so make it a good one. */
874 silc_server_packet_send(server, entry->router->connection,
875 SILC_PACKET_COMMAND, cmd->packet->flags,
876 tmpbuf->data, tmpbuf->len, TRUE);
878 /* Reprocess this packet after received reply */
879 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
880 silc_command_get_ident(cmd->payload),
881 silc_server_command_destructor,
882 silc_server_command_identify,
883 silc_server_command_dup(cmd));
887 /* Put old data back to the Command Payload we just changed */
888 silc_command_set_ident(cmd->payload, old_ident);
889 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
891 silc_buffer_free(tmpbuf);
900 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
901 SilcClientEntry *clients,
902 unsigned int clients_count)
904 SilcServer server = cmd->server;
906 int i, count = 0, len;
907 SilcBuffer packet, idp;
908 SilcClientEntry entry;
909 SilcCommandStatus status;
910 unsigned short ident = silc_command_get_ident(cmd->payload);
912 status = SILC_STATUS_OK;
913 if (clients_count > 1)
914 status = SILC_STATUS_LIST_START;
916 for (i = 0; i < clients_count; i++) {
919 if (count && i - 1 == count)
922 if (clients_count > 2)
923 status = SILC_STATUS_LIST_ITEM;
925 if (clients_count > 1 && i == clients_count - 1)
926 status = SILC_STATUS_LIST_END;
928 /* Send IDENTIFY reply */
929 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
930 tmp = silc_argument_get_first_arg(cmd->args, NULL);
934 char nh[256], uh[256];
935 SilcSocketConnection hsock;
937 memset(uh, 0, sizeof(uh));
938 memset(nh, 0, sizeof(nh));
940 strncat(nh, entry->nickname, strlen(entry->nickname));
941 if (!strchr(entry->nickname, '@')) {
943 len = entry->router ? strlen(entry->router->server_name) :
944 strlen(server->server_name);
945 strncat(nh, entry->router ? entry->router->server_name :
946 server->server_name, len);
949 if (!entry->username) {
950 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
952 2, idp->data, idp->len,
955 strncat(uh, entry->username, strlen(entry->username));
956 if (!strchr(entry->username, '@')) {
958 hsock = (SilcSocketConnection)entry->connection;
959 len = strlen(hsock->hostname);
960 strncat(uh, hsock->hostname, len);
963 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
965 2, idp->data, idp->len,
970 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
971 0, packet->data, packet->len, FALSE);
973 silc_buffer_free(packet);
974 silc_buffer_free(idp);
980 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
982 SilcServer server = cmd->server;
983 char *nick = NULL, *server_name = NULL;
984 int count = 0, clients_count = 0;
985 SilcClientEntry *clients = NULL, entry;
986 SilcClientID **client_id = NULL;
987 unsigned int client_id_count = 0;
990 /* Protocol dictates that we must always send the received IDENTIFY request
991 to our router if we are normal server, so let's do it now unless we
992 are standalone. We will not send any replies to the client until we
993 have received reply from the router. */
994 if (server->server_type == SILC_SERVER &&
995 !cmd->pending && !server->standalone) {
997 unsigned short old_ident;
999 old_ident = silc_command_get_ident(cmd->payload);
1000 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1001 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1003 /* Send IDENTIFY command to our router */
1004 silc_server_packet_send(server, (SilcSocketConnection)
1005 server->router->connection,
1006 SILC_PACKET_COMMAND, cmd->packet->flags,
1007 tmpbuf->data, tmpbuf->len, TRUE);
1009 /* Reprocess this packet after received reply from router */
1010 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1011 silc_command_get_ident(cmd->payload),
1012 silc_server_command_destructor,
1013 silc_server_command_identify,
1014 silc_server_command_dup(cmd));
1015 cmd->pending = TRUE;
1017 silc_command_set_ident(cmd->payload, old_ident);
1019 silc_buffer_free(tmpbuf);
1024 /* We are ready to process the command request. Let's search for the
1025 requested client and send reply to the requesting client. */
1027 /* Parse the IDENTIFY request */
1028 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1029 &nick, &server_name, &count,
1030 SILC_COMMAND_IDENTIFY))
1033 /* Get all clients matching that ID or nickname from local list */
1034 if (client_id_count) {
1035 /* Check all Client ID's received in the command packet */
1036 for (i = 0; i < client_id_count; i++) {
1037 entry = silc_idlist_find_client_by_id(server->local_list,
1038 client_id[i], NULL);
1040 clients = silc_realloc(clients, sizeof(*clients) *
1041 (clients_count + 1));
1042 clients[clients_count++] = entry;
1046 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1050 clients = silc_idlist_get_clients_by_hash(server->local_list,
1051 nick, server->md5hash,
1055 /* Check global list as well */
1057 if (client_id_count) {
1058 /* Check all Client ID's received in the command packet */
1059 for (i = 0; i < client_id_count; i++) {
1060 entry = silc_idlist_find_client_by_id(server->global_list,
1061 client_id[i], NULL);
1063 clients = silc_realloc(clients, sizeof(*clients) *
1064 (clients_count + 1));
1065 clients[clients_count++] = entry;
1069 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1073 clients = silc_idlist_get_clients_by_hash(server->global_list,
1074 nick, server->md5hash,
1080 /* Such a client really does not exist in the SILC network. */
1081 if (!client_id_count) {
1082 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1083 SILC_STATUS_ERR_NO_SUCH_NICK,
1084 3, nick, strlen(nick));
1086 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1087 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1088 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1089 2, idp->data, idp->len);
1090 silc_buffer_free(idp);
1095 /* Check that all mandatory fields are present and request those data
1096 from the server who owns the client if necessary. */
1097 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1102 /* Send the command reply to the client */
1103 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1106 if (client_id_count) {
1107 for (i = 0; i < client_id_count; i++)
1108 silc_free(client_id[i]);
1109 silc_free(client_id);
1116 silc_free(server_name);
1122 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1124 SilcServer server = cmd->server;
1125 char *nick = NULL, *server_name = NULL;
1126 int count = 0, clients_count = 0;
1127 SilcClientEntry *clients = NULL, entry;
1128 SilcClientID **client_id = NULL;
1129 unsigned int client_id_count = 0;
1132 /* Parse the IDENTIFY request */
1133 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1134 &nick, &server_name, &count,
1135 SILC_COMMAND_IDENTIFY))
1138 /* Process the command request. Let's search for the requested client and
1139 send reply to the requesting server. */
1141 if (client_id_count) {
1142 /* Check all Client ID's received in the command packet */
1143 for (i = 0; i < client_id_count; i++) {
1144 entry = silc_idlist_find_client_by_id(server->local_list,
1145 client_id[i], NULL);
1147 clients = silc_realloc(clients, sizeof(*clients) *
1148 (clients_count + 1));
1149 clients[clients_count++] = entry;
1153 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1157 clients = silc_idlist_get_clients_by_hash(server->local_list,
1158 nick, server->md5hash,
1162 /* If we are router we will check our global list as well. */
1163 if (!clients && server->server_type == SILC_ROUTER) {
1164 if (client_id_count) {
1165 /* Check all Client ID's received in the command packet */
1166 for (i = 0; i < client_id_count; i++) {
1167 entry = silc_idlist_find_client_by_id(server->global_list,
1168 client_id[i], NULL);
1170 clients = silc_realloc(clients, sizeof(*clients) *
1171 (clients_count + 1));
1172 clients[clients_count++] = entry;
1176 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1180 clients = silc_idlist_get_clients_by_hash(server->global_list,
1181 nick, server->md5hash,
1187 /* Such a client really does not exist in the SILC network. */
1188 if (!client_id_count) {
1189 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1190 SILC_STATUS_ERR_NO_SUCH_NICK,
1191 3, nick, strlen(nick));
1193 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1194 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1195 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1196 2, idp->data, idp->len);
1197 silc_buffer_free(idp);
1202 /* Check that all mandatory fields are present and request those data
1203 from the server who owns the client if necessary. */
1204 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1209 /* Send the command reply */
1210 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1213 if (client_id_count) {
1214 for (i = 0; i < client_id_count; i++)
1215 silc_free(client_id[i]);
1216 silc_free(client_id);
1223 silc_free(server_name);
1228 SILC_SERVER_CMD_FUNC(identify)
1230 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1233 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1235 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1236 ret = silc_server_command_identify_from_client(cmd);
1237 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1238 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1239 ret = silc_server_command_identify_from_server(cmd);
1242 silc_server_command_free(cmd);
1245 /* Checks string for bad characters and returns TRUE if they are found. */
1247 static int silc_server_command_bad_chars(char *nick)
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;
1254 if (strchr(nick, '*')) return TRUE;
1255 if (strchr(nick, '/')) return TRUE;
1256 if (strchr(nick, '@')) return TRUE;
1261 /* Server side of command NICK. Sets nickname for user. Setting
1262 nickname causes generation of a new client ID for the client. The
1263 new client ID is sent to the client after changing the nickname. */
1265 SILC_SERVER_CMD_FUNC(nick)
1267 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1268 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1269 SilcServer server = cmd->server;
1270 SilcBuffer packet, nidp, oidp;
1271 SilcClientID *new_id;
1274 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1276 /* Check nickname */
1277 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1278 if (silc_server_command_bad_chars(nick) == TRUE) {
1279 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1280 SILC_STATUS_ERR_BAD_NICKNAME);
1284 if (strlen(nick) > 128)
1287 /* Create new Client ID */
1288 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1289 cmd->server->md5hash, nick,
1292 /* Send notify about nickname change to our router. We send the new
1293 ID and ask to replace it with the old one. If we are router the
1294 packet is broadcasted. Send NICK_CHANGE notify. */
1295 if (!server->standalone)
1296 silc_server_send_notify_nick_change(server, server->router->connection,
1297 server->server_type == SILC_SERVER ?
1298 FALSE : TRUE, client->id,
1299 new_id, SILC_ID_CLIENT_LEN);
1301 /* Remove old cache entry */
1302 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1305 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1309 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1310 silc_free(client->id);
1313 /* Save the nickname as this client is our local client */
1314 if (client->nickname)
1315 silc_free(client->nickname);
1317 client->nickname = strdup(nick);
1318 client->id = new_id;
1320 /* Update client cache */
1321 silc_idcache_add(server->local_list->clients, client->nickname,
1322 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1324 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1326 /* Send NICK_CHANGE notify to the client's channels */
1327 silc_server_send_notify_on_channels(server, client,
1328 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1329 oidp->data, oidp->len,
1330 nidp->data, nidp->len);
1332 /* Send the new Client ID as reply command back to client */
1333 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1334 SILC_STATUS_OK, 0, 1,
1335 2, nidp->data, nidp->len);
1336 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1337 0, packet->data, packet->len, FALSE);
1339 silc_buffer_free(packet);
1340 silc_buffer_free(nidp);
1341 silc_buffer_free(oidp);
1344 silc_server_command_free(cmd);
1347 SILC_SERVER_CMD_FUNC(list)
1351 /* Server side of TOPIC command. Sets topic for channel and/or returns
1352 current topic to client. */
1354 SILC_SERVER_CMD_FUNC(topic)
1356 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1357 SilcServer server = cmd->server;
1358 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1359 SilcChannelID *channel_id;
1360 SilcChannelEntry channel;
1361 SilcChannelClientEntry chl;
1362 SilcBuffer packet, idp;
1364 unsigned int argc, tmp_len;
1366 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1368 argc = silc_argument_get_arg_num(cmd->args);
1370 /* Get Channel ID */
1371 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1374 SILC_STATUS_ERR_NO_CHANNEL_ID);
1377 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1379 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1380 SILC_STATUS_ERR_NO_CHANNEL_ID);
1384 /* Check whether the channel exists */
1385 channel = silc_idlist_find_channel_by_id(server->local_list,
1388 channel = silc_idlist_find_channel_by_id(server->global_list,
1391 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1392 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1399 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1401 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1402 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1406 if (strlen(tmp) > 256) {
1407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1408 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1412 /* See whether has rights to change topic */
1413 silc_list_start(channel->user_list);
1414 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1415 if (chl->client == client)
1418 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1419 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1420 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1421 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1426 /* Set the topic for channel */
1428 silc_free(channel->topic);
1429 channel->topic = strdup(tmp);
1431 /* Send TOPIC_SET notify type to the network */
1432 if (!server->standalone)
1433 silc_server_send_notify_topic_set(server, server->router->connection,
1434 server->server_type == SILC_ROUTER ?
1435 TRUE : FALSE, channel, client->id,
1436 SILC_ID_CLIENT_LEN, channel->topic);
1438 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1440 /* Send notify about topic change to all clients on the channel */
1441 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1442 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1443 idp->data, idp->len,
1444 channel->topic, strlen(channel->topic));
1445 silc_buffer_free(idp);
1448 /* Send the topic to client as reply packet */
1449 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1451 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1452 SILC_STATUS_OK, 0, 2,
1453 2, idp->data, idp->len,
1455 strlen(channel->topic));
1457 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1458 SILC_STATUS_OK, 0, 1,
1459 2, idp->data, idp->len);
1460 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1461 0, packet->data, packet->len, FALSE);
1463 silc_buffer_free(packet);
1464 silc_buffer_free(idp);
1465 silc_free(channel_id);
1468 silc_server_command_free(cmd);
1471 /* Server side of INVITE command. Invites some client to join some channel. */
1473 SILC_SERVER_CMD_FUNC(invite)
1475 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1476 SilcServer server = cmd->server;
1477 SilcSocketConnection sock = cmd->sock, dest_sock;
1478 SilcClientEntry sender, dest;
1479 SilcClientID *dest_id;
1480 SilcChannelEntry channel;
1481 SilcChannelID *channel_id;
1486 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1488 /* Get destination ID */
1489 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1491 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1492 SILC_STATUS_ERR_NO_CLIENT_ID);
1495 dest_id = silc_id_payload_parse_id(tmp, len);
1497 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1498 SILC_STATUS_ERR_NO_CLIENT_ID);
1502 /* Get Channel ID */
1503 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1506 SILC_STATUS_ERR_NO_CHANNEL_ID);
1509 channel_id = silc_id_payload_parse_id(tmp, len);
1511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1512 SILC_STATUS_ERR_NO_CHANNEL_ID);
1516 /* Check whether the channel exists */
1517 channel = silc_idlist_find_channel_by_id(server->local_list,
1520 channel = silc_idlist_find_channel_by_id(server->global_list,
1523 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1524 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1529 /* Check whether the sender of this command is on the channel. */
1530 sender = (SilcClientEntry)sock->user_data;
1531 if (!silc_server_client_on_channel(sender, channel)) {
1532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1533 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1537 /* Check whether the channel is invite-only channel. If yes then the
1538 sender of this command must be at least channel operator. */
1539 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1540 SilcChannelClientEntry chl;
1542 silc_list_start(channel->user_list);
1543 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1544 if (chl->client == sender) {
1545 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1547 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1554 /* Find the connection data for the destination. If it is local we will
1555 send it directly otherwise we will send it to router for routing. */
1556 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1558 dest_sock = (SilcSocketConnection)dest->connection;
1560 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1562 /* Check whether the requested client is already on the channel. */
1563 /* XXX if we are normal server we don't know about global clients on
1564 the channel thus we must request it (USERS command), check from
1565 local cache as well. */
1566 if (silc_server_client_on_channel(dest, channel)) {
1567 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1568 SILC_STATUS_ERR_USER_ON_CHANNEL);
1572 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1574 /* Send notify to the client that is invited to the channel */
1575 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1577 SILC_NOTIFY_TYPE_INVITE, 2,
1578 sidp->data, sidp->len, tmp, len);
1580 /* Send command reply */
1581 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1584 silc_buffer_free(sidp);
1587 silc_server_command_free(cmd);
1592 SilcSocketConnection sock;
1596 /* Quits connection to client. This gets called if client won't
1597 close the connection even when it has issued QUIT command. */
1599 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1601 QuitInternal q = (QuitInternal)context;
1603 /* Free all client specific data, such as client entry and entires
1604 on channels this client may be on. */
1605 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1607 q->sock->user_data = NULL;
1609 /* Close the connection on our side */
1610 silc_server_close_connection(q->server, q->sock);
1612 silc_free(q->signoff);
1616 /* Quits SILC session. This is the normal way to disconnect client. */
1618 SILC_SERVER_CMD_FUNC(quit)
1620 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1621 SilcServer server = cmd->server;
1622 SilcSocketConnection sock = cmd->sock;
1624 unsigned char *tmp = NULL;
1625 unsigned int len = 0;
1627 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
1629 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1632 /* Get destination ID */
1633 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1637 q = silc_calloc(1, sizeof(*q));
1640 q->signoff = tmp ? strdup(tmp) : NULL;
1642 /* We quit the connection with little timeout */
1643 silc_task_register(server->timeout_queue, sock->sock,
1644 silc_server_command_quit_cb, (void *)q,
1645 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1648 silc_server_command_free(cmd);
1651 SILC_SERVER_CMD_FUNC(kill)
1655 /* Server side of command INFO. This sends information about us to
1656 the client. If client requested specific server we will send the
1657 command to that server. */
1659 SILC_SERVER_CMD_FUNC(info)
1661 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1662 SilcServer server = cmd->server;
1663 SilcBuffer packet, idp;
1664 char info_string[256], *dest_server;
1666 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1668 /* Get server name */
1669 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1671 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1672 SILC_STATUS_ERR_NO_SUCH_SERVER);
1676 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1677 /* Send our reply */
1678 memset(info_string, 0, sizeof(info_string));
1679 snprintf(info_string, sizeof(info_string),
1680 "location: %s server: %s admin: %s <%s>",
1681 server->config->admin_info->location,
1682 server->config->admin_info->server_type,
1683 server->config->admin_info->admin_name,
1684 server->config->admin_info->admin_email);
1686 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1688 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1689 SILC_STATUS_OK, 0, 2,
1690 2, idp->data, idp->len,
1692 strlen(info_string));
1693 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1694 packet->data, packet->len, FALSE);
1696 silc_buffer_free(packet);
1697 silc_buffer_free(idp);
1699 /* Send this command to the requested server */
1701 if (server->server_type == SILC_SERVER && !server->standalone) {
1705 if (server->server_type == SILC_ROUTER) {
1711 silc_server_command_free(cmd);
1714 /* Server side of command PING. This just replies to the ping. */
1716 SILC_SERVER_CMD_FUNC(ping)
1718 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1719 SilcServer server = cmd->server;
1724 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1727 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1730 SILC_STATUS_ERR_NO_SERVER_ID);
1733 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1737 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1738 /* Send our reply */
1739 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1742 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1743 SILC_STATUS_ERR_NO_SUCH_SERVER);
1750 silc_server_command_free(cmd);
1753 /* Internal routine to join channel. The channel sent to this function
1754 has been either created or resolved from ID lists. This joins the sent
1755 client to the channel. */
1757 static void silc_server_command_join_channel(SilcServer server,
1758 SilcServerCommandContext cmd,
1759 SilcChannelEntry channel,
1760 SilcClientID *client_id,
1764 SilcSocketConnection sock = cmd->sock;
1766 unsigned int tmp_len, user_count;
1767 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
1768 SilcClientEntry client;
1769 SilcChannelClientEntry chl;
1770 SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
1771 unsigned short ident = silc_command_get_ident(cmd->payload);
1773 SILC_LOG_DEBUG(("Start"));
1778 /* Get passphrase */
1779 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1781 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1782 memcpy(passphrase, tmp, tmp_len);
1786 * Check channel modes
1789 /* Check invite list if channel is invite-only channel */
1790 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1791 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1792 /* Invite list is specified. Check whether client is invited in the
1793 list. If not, then check whether it has been invited otherwise. */
1796 /* XXX client must be invited to be able to join the channel */
1800 /* Check ban list if set */
1801 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1805 /* Check the channel passphrase if set. */
1806 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1807 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1808 strlen(channel->mode_data.passphrase))) {
1809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1810 SILC_STATUS_ERR_BAD_PASSWORD);
1815 /* Check user count limit if set. */
1816 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1817 if (silc_list_count(channel->user_list) + 1 >
1818 channel->mode_data.user_limit) {
1819 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1820 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1826 * Client is allowed to join to the channel. Make it happen.
1829 /* Get the client entry */
1830 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1831 client = (SilcClientEntry)sock->user_data;
1833 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1836 /* XXX actually this is useless since router finds always cell's
1837 local clients from its local lists. */
1838 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1845 /* Check whether the client already is on the channel */
1846 if (silc_server_client_on_channel(client, channel)) {
1847 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1848 SILC_STATUS_ERR_USER_ON_CHANNEL);
1852 /* Generate new channel key as protocol dictates */
1853 if ((!created && silc_list_count(channel->user_list) > 0) ||
1854 !channel->channel_key)
1855 silc_server_create_channel_key(server, channel, 0);
1857 /* Send the channel key. This is broadcasted to the channel but is not
1858 sent to the client who is joining to the channel. */
1859 silc_server_send_channel_key(server, NULL, channel,
1860 server->server_type == SILC_ROUTER ?
1861 FALSE : !server->standalone);
1863 /* Join the client to the channel by adding it to channel's user list.
1864 Add also the channel to client entry's channels list for fast cross-
1866 chl = silc_calloc(1, sizeof(*chl));
1868 chl->client = client;
1869 chl->channel = channel;
1870 silc_list_add(channel->user_list, chl);
1871 silc_list_add(client->channels, chl);
1873 /* Get users on the channel */
1874 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
1877 /* Encode Client ID Payload of the original client who wants to join */
1878 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1880 /* Encode command reply packet */
1881 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1882 SILC_PUT32_MSB(channel->mode, mode);
1883 SILC_PUT32_MSB(created, tmp2);
1884 SILC_PUT32_MSB(user_count, tmp3);
1885 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1886 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1887 strlen(channel->channel_key->
1889 channel->channel_key->cipher->name,
1890 channel->key_len / 8, channel->key);
1892 if (!channel->topic) {
1894 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1895 SILC_STATUS_OK, ident, 9,
1896 2, channel->channel_name,
1897 strlen(channel->channel_name),
1898 3, chidp->data, chidp->len,
1899 4, clidp->data, clidp->len,
1902 7, keyp->data, keyp->len,
1904 13, user_list->data, user_list->len,
1905 14, mode_list->data,
1909 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1910 SILC_STATUS_OK, ident, 10,
1911 2, channel->channel_name,
1912 strlen(channel->channel_name),
1913 3, chidp->data, chidp->len,
1914 4, clidp->data, clidp->len,
1917 7, keyp->data, keyp->len,
1919 strlen(channel->topic),
1921 13, user_list->data, user_list->len,
1922 14, mode_list->data,
1926 /* Send command reply */
1927 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1928 reply->data, reply->len, FALSE);
1930 if (!cmd->pending) {
1931 /* Send JOIN notify to locally connected clients on the channel */
1932 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1933 SILC_NOTIFY_TYPE_JOIN, 2,
1934 clidp->data, clidp->len,
1935 chidp->data, chidp->len);
1937 /* Send JOIN notify packet to our primary router */
1938 if (!server->standalone)
1939 silc_server_send_notify_join(server, server->router->connection,
1940 server->server_type == SILC_ROUTER ?
1941 TRUE : FALSE, channel, client->id,
1942 SILC_ID_CLIENT_LEN);
1945 silc_buffer_free(reply);
1946 silc_buffer_free(clidp);
1947 silc_buffer_free(chidp);
1948 silc_buffer_free(keyp);
1949 silc_buffer_free(user_list);
1950 silc_buffer_free(mode_list);
1954 silc_free(passphrase);
1957 /* Server side of command JOIN. Joins client into requested channel. If
1958 the channel does not exist it will be created. */
1960 SILC_SERVER_CMD_FUNC(join)
1962 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1963 SilcServer server = cmd->server;
1965 char *tmp, *channel_name = NULL, *cipher, *hmac;
1966 SilcChannelEntry channel;
1967 unsigned int umode = 0;
1968 int created = FALSE;
1969 SilcClientID *client_id;
1971 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1973 /* Get channel name */
1974 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1977 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1982 if (strlen(channel_name) > 256)
1983 channel_name[255] = '\0';
1985 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1986 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1987 SILC_STATUS_ERR_BAD_CHANNEL);
1988 silc_free(channel_name);
1992 /* Get Client ID of the client who is joining to the channel */
1993 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1995 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1996 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1999 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2001 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2002 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2006 /* Get cipher and hmac name */
2007 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2008 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2010 /* See if the channel exists */
2011 channel = silc_idlist_find_channel_by_name(server->local_list,
2012 channel_name, NULL);
2014 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2015 /* If this is coming from client the Client ID in the command packet must
2016 be same as the client's ID. */
2017 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2018 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2019 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2021 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2027 /* Channel not found */
2029 /* If we are standalone server we don't have a router, we just create
2030 the channel by ourselves. */
2031 if (server->standalone) {
2032 channel = silc_server_create_new_channel(server, server->id, cipher,
2033 hmac, channel_name, TRUE);
2034 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2039 /* The channel does not exist on our server. If we are normal server
2040 we will send JOIN command to our router which will handle the
2041 joining procedure (either creates the channel if it doesn't exist
2042 or joins the client to it). */
2043 if (server->server_type == SILC_SERVER) {
2045 unsigned short old_ident;
2047 old_ident = silc_command_get_ident(cmd->payload);
2048 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2049 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2051 /* Send JOIN command to our router */
2052 silc_server_packet_send(server, (SilcSocketConnection)
2053 server->router->connection,
2054 SILC_PACKET_COMMAND, cmd->packet->flags,
2055 tmpbuf->data, tmpbuf->len, TRUE);
2057 /* Reprocess this packet after received reply from router */
2058 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2059 silc_command_get_ident(cmd->payload),
2060 silc_server_command_destructor,
2061 silc_server_command_join,
2062 silc_server_command_dup(cmd));
2063 cmd->pending = TRUE;
2067 /* We are router and the channel does not seem exist so we will check
2068 our global list as well for the channel. */
2069 channel = silc_idlist_find_channel_by_name(server->global_list,
2070 channel_name, NULL);
2072 /* Channel really does not exist, create it */
2073 channel = silc_server_create_new_channel(server, server->id, cipher,
2074 hmac, channel_name, TRUE);
2075 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2082 /* Channel not found */
2084 /* If the command came from router and/or we are normal server then
2085 something went wrong with the joining as the channel was not found.
2086 We can't do anything else but ignore this. */
2087 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2088 server->server_type == SILC_SERVER)
2091 /* We are router and the channel does not seem exist so we will check
2092 our global list as well for the channel. */
2093 channel = silc_idlist_find_channel_by_name(server->global_list,
2094 channel_name, NULL);
2096 /* Channel really does not exist, create it */
2097 channel = silc_server_create_new_channel(server, server->id, cipher,
2098 hmac, channel_name, TRUE);
2099 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2105 /* If the channel does not have global users and is also empty it means the
2106 channel was created globally (by our router) and the client will be the
2107 channel founder and operator. */
2108 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2109 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2110 created = TRUE; /* Created globally by our router */
2113 /* Join to the channel */
2114 silc_server_command_join_channel(server, cmd, channel, client_id,
2117 silc_free(client_id);
2120 silc_server_command_free(cmd);
2123 /* Server side of command MOTD. Sends server's current "message of the
2124 day" to the client. */
2126 SILC_SERVER_CMD_FUNC(motd)
2128 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2129 SilcServer server = cmd->server;
2133 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2135 /* XXX show currently only our motd */
2137 if (server->config && server->config->motd &&
2138 server->config->motd->motd_file) {
2141 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2146 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2152 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2157 silc_server_command_free(cmd);
2160 SILC_SERVER_CMD_FUNC(umode)
2164 /* Checks that client has rights to add or remove channel modes. If any
2165 of the checks fails FALSE is returned. */
2167 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2168 SilcChannelClientEntry client,
2171 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2172 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2174 /* Check whether has rights to change anything */
2175 if (!is_op && !is_fo)
2178 /* Check whether has rights to change everything */
2182 /* We know that client is channel operator, check that they are not
2183 changing anything that requires channel founder rights. Rest of the
2184 modes are available automatically for channel operator. */
2186 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2187 if (is_op && !is_fo)
2190 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2191 if (is_op && !is_fo)
2196 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2197 if (is_op && !is_fo)
2200 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2201 if (is_op && !is_fo)
2206 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2207 if (is_op && !is_fo)
2210 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2211 if (is_op && !is_fo)
2219 /* Server side command of CMODE. Changes channel mode */
2221 SILC_SERVER_CMD_FUNC(cmode)
2223 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2224 SilcServer server = cmd->server;
2225 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2226 SilcChannelID *channel_id;
2227 SilcChannelEntry channel;
2228 SilcChannelClientEntry chl;
2229 SilcBuffer packet, cidp;
2230 unsigned char *tmp, *tmp_id, *tmp_mask;
2231 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2233 SILC_LOG_DEBUG(("Start"));
2235 argc = silc_argument_get_arg_num(cmd->args);
2237 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2238 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2243 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2247 /* Get Channel ID */
2248 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2250 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2251 SILC_STATUS_ERR_NO_CHANNEL_ID);
2254 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2256 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2257 SILC_STATUS_ERR_NO_CHANNEL_ID);
2261 /* Get the channel mode mask */
2262 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2264 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2265 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2268 SILC_GET32_MSB(mode_mask, tmp_mask);
2270 /* Get channel entry */
2271 channel = silc_idlist_find_channel_by_id(server->local_list,
2274 channel = silc_idlist_find_channel_by_id(server->global_list,
2277 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2278 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2283 /* Check whether this client is on the channel */
2284 if (!silc_server_client_on_channel(client, channel)) {
2285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2286 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2290 /* Get entry to the channel user list */
2291 silc_list_start(channel->user_list);
2292 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2293 if (chl->client == client)
2296 /* Check that client has rights to change any requested channel modes */
2297 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2299 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2304 * Check the modes. Modes that requires nothing special operation are
2308 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2309 /* Channel uses private keys to protect traffic. Client(s) has set the
2310 key locally they want to use, server does not know that key. */
2311 /* Nothing interesting to do here now */
2313 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2314 /* The mode is removed and we need to generate and distribute
2315 new channel key. Clients are not using private channel keys
2316 anymore after this. */
2318 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2321 /* Re-generate channel key */
2322 silc_server_create_channel_key(server, channel, 0);
2324 /* Encode channel key payload to be distributed on the channel */
2326 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2327 strlen(channel->channel_key->
2329 channel->channel_key->cipher->name,
2330 channel->key_len / 8, channel->key);
2332 /* If we are normal server then we will send it to our router. If we
2333 are router we will send it to all local servers that has clients on
2335 if (server->server_type == SILC_SERVER) {
2336 if (!server->standalone)
2337 silc_server_packet_send(server,
2338 cmd->server->router->connection,
2339 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2345 /* Send to locally connected clients on the channel */
2346 silc_server_packet_send_local_channel(server, channel,
2347 SILC_PACKET_CHANNEL_KEY, 0,
2348 packet->data, packet->len, FALSE);
2349 silc_buffer_free(packet);
2353 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2354 /* User limit is set on channel */
2355 unsigned int user_limit;
2357 /* Get user limit */
2358 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2360 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2361 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2362 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2366 SILC_GET32_MSB(user_limit, tmp);
2367 channel->mode_data.user_limit = user_limit;
2370 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2371 /* User limit mode is unset. Remove user limit */
2372 channel->mode_data.user_limit = 0;
2375 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2376 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2377 /* Passphrase has been set to channel */
2379 /* Get the passphrase */
2380 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2383 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2387 /* Save the passphrase */
2388 channel->mode_data.passphrase = strdup(tmp);
2391 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2392 /* Passphrase mode is unset. remove the passphrase */
2393 if (channel->mode_data.passphrase) {
2394 silc_free(channel->mode_data.passphrase);
2395 channel->mode_data.passphrase = NULL;
2400 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2401 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2402 /* Ban list is specified for channel */
2405 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2408 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2412 /* XXX check that channel founder is not banned */
2414 /* Save the ban list */
2415 channel->mode_data.ban_list = strdup(tmp);
2418 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2419 /* Ban mode is unset. Remove the entire ban list */
2420 if (channel->mode_data.ban_list) {
2421 silc_free(channel->mode_data.ban_list);
2422 channel->mode_data.ban_list = NULL;
2427 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2428 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2429 /* Invite list is specified for channel */
2431 /* Get invite list */
2432 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2435 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2439 /* Save the invite linst */
2440 channel->mode_data.invite_list = strdup(tmp);
2443 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2444 /* Invite list mode is unset. Remove the entire invite list */
2445 if (channel->mode_data.invite_list) {
2446 silc_free(channel->mode_data.invite_list);
2447 channel->mode_data.invite_list = NULL;
2452 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2453 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2454 /* Cipher to use protect the traffic */
2455 unsigned int key_len;
2458 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2461 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2465 /* XXX Duplicated code, make own function for this!! */
2467 /* Delete old cipher and allocate the new one */
2468 silc_cipher_free(channel->channel_key);
2469 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
2470 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2471 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2474 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
2476 /* Re-generate channel key */
2477 silc_server_create_channel_key(server, channel, key_len);
2479 /* Encode channel key payload to be distributed on the channel */
2481 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2482 strlen(channel->channel_key->
2484 channel->channel_key->cipher->name,
2485 channel->key_len / 8, channel->key);
2487 /* If we are normal server then we will send it to our router. If we
2488 are router we will send it to all local servers that has clients on
2490 if (server->server_type == SILC_SERVER) {
2491 if (!server->standalone)
2492 silc_server_packet_send(server,
2493 cmd->server->router->connection,
2494 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2500 /* Send to locally connected clients on the channel */
2501 silc_server_packet_send_local_channel(server, channel,
2502 SILC_PACKET_CHANNEL_KEY, 0,
2503 packet->data, packet->len, FALSE);
2504 silc_buffer_free(packet);
2507 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2508 /* Cipher mode is unset. Remove the cipher and revert back to
2511 if (channel->mode_data.cipher) {
2512 silc_free(channel->mode_data.cipher);
2513 channel->mode_data.cipher = NULL;
2514 channel->mode_data.key_len = 0;
2517 /* Generate new cipher and key for the channel */
2519 /* XXX Duplicated code, make own function for this!! */
2521 /* Delete old cipher and allocate default one */
2522 silc_cipher_free(channel->channel_key);
2523 if (!channel->cipher)
2524 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
2526 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
2527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2528 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2533 /* Re-generate channel key */
2534 silc_server_create_channel_key(server, channel, 0);
2536 /* Encode channel key payload to be distributed on the channel */
2538 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2539 strlen(channel->channel_key->
2541 channel->channel_key->cipher->name,
2542 channel->key_len / 8, channel->key);
2544 /* If we are normal server then we will send it to our router. If we
2545 are router we will send it to all local servers that has clients on
2547 if (server->server_type == SILC_SERVER) {
2548 if (!server->standalone)
2549 silc_server_packet_send(server,
2550 cmd->server->router->connection,
2551 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2557 /* Send to locally connected clients on the channel */
2558 silc_server_packet_send_local_channel(server, channel,
2559 SILC_PACKET_CHANNEL_KEY, 0,
2560 packet->data, packet->len, FALSE);
2561 silc_buffer_free(packet);
2565 /* Finally, set the mode */
2566 channel->mode = mode_mask;
2568 /* Send CMODE_CHANGE notify */
2569 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2570 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2571 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2572 cidp->data, cidp->len,
2575 /* Set CMODE notify type to network */
2576 if (!server->standalone)
2577 silc_server_send_notify_cmode(server, server->router->connection,
2578 server->server_type == SILC_ROUTER ?
2579 TRUE : FALSE, channel,
2580 mode_mask, client->id, SILC_ID_CLIENT_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 channel = silc_idlist_find_channel_by_id(server->global_list,
2637 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2638 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2643 /* Check whether sender is on the channel */
2644 if (!silc_server_client_on_channel(client, channel)) {
2645 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2646 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2650 /* Check that client has rights to change other's rights */
2651 silc_list_start(channel->user_list);
2652 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2653 if (chl->client == client) {
2654 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2655 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2656 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2657 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2661 sender_mask = chl->mode;
2666 /* Get the target client's channel mode mask */
2667 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2670 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2673 SILC_GET32_MSB(target_mask, tmp_mask);
2675 /* Get target Client ID */
2676 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2678 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2679 SILC_STATUS_ERR_NO_CLIENT_ID);
2682 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2685 SILC_STATUS_ERR_NO_CLIENT_ID);
2689 /* Get target client's entry */
2690 target_client = silc_idlist_find_client_by_id(server->local_list,
2692 if (!target_client) {
2693 target_client = silc_idlist_find_client_by_id(server->global_list,
2697 /* Check whether target client is on the channel */
2698 if (!silc_server_client_on_channel(target_client, channel)) {
2699 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2700 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2704 /* Get entry to the channel user list */
2705 silc_list_start(channel->user_list);
2706 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2707 if (chl->client == target_client)
2714 /* If the target client is founder, no one else can change their mode
2716 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2717 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2718 SILC_STATUS_ERR_NOT_YOU);
2722 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2723 /* Cannot promote anyone to channel founder */
2724 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2725 SILC_STATUS_ERR_NOT_YOU);
2728 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2729 if (target_client == client) {
2730 /* Remove channel founder rights from itself */
2731 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2734 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2735 SILC_STATUS_ERR_NOT_YOU);
2741 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2742 /* Promote to operator */
2743 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2744 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2748 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2749 /* Demote to normal user */
2750 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2755 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2757 /* Send notify to channel, notify only if mode was actually changed. */
2759 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2760 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2761 idp->data, idp->len,
2765 /* Set CUMODE notify type to network */
2766 if (!server->standalone)
2767 silc_server_send_notify_cumode(server, server->router->connection,
2768 server->server_type == SILC_ROUTER ?
2769 TRUE : FALSE, channel,
2770 target_mask, client->id,
2773 SILC_ID_CLIENT_LEN);
2776 /* Send command reply to sender */
2777 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2778 SILC_STATUS_OK, 0, 2,
2780 3, tmp_id, tmp_len);
2781 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2782 packet->data, packet->len, FALSE);
2784 silc_buffer_free(packet);
2785 silc_free(channel_id);
2786 silc_free(client_id);
2787 silc_buffer_free(idp);
2790 silc_server_command_free(cmd);
2793 /* Server side of KICK command. Kicks client out of channel. */
2795 SILC_SERVER_CMD_FUNC(kick)
2797 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2798 SilcServer server = cmd->server;
2799 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2800 SilcClientEntry target_client;
2801 SilcChannelID *channel_id;
2802 SilcClientID *client_id;
2803 SilcChannelEntry channel;
2804 SilcChannelClientEntry chl;
2806 unsigned int tmp_len;
2807 unsigned char *tmp, *comment;
2809 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
2811 /* Get Channel ID */
2812 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2815 SILC_STATUS_ERR_NO_CHANNEL_ID);
2818 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2820 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2821 SILC_STATUS_ERR_NO_CHANNEL_ID);
2825 /* Get channel entry */
2826 channel = silc_idlist_find_channel_by_id(server->local_list,
2829 channel = silc_idlist_find_channel_by_id(server->local_list,
2832 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2833 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2838 /* Check whether sender is on the channel */
2839 if (!silc_server_client_on_channel(client, channel)) {
2840 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2841 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2845 /* Check that the kicker is channel operator or channel founder */
2846 silc_list_start(channel->user_list);
2847 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2848 if (chl->client == client) {
2849 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2850 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2851 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2858 /* Get target Client ID */
2859 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2862 SILC_STATUS_ERR_NO_CLIENT_ID);
2865 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2867 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2868 SILC_STATUS_ERR_NO_CLIENT_ID);
2872 /* Get target client's entry */
2873 target_client = silc_idlist_find_client_by_id(server->local_list,
2875 if (!target_client) {
2876 target_client = silc_idlist_find_client_by_id(server->global_list,
2880 /* Check that the target client is not channel founder. Channel founder
2881 cannot be kicked from the channel. */
2882 silc_list_start(channel->user_list);
2883 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2884 if (chl->client == target_client) {
2885 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2886 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2887 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
2894 /* Check whether target client is on the channel */
2895 if (!silc_server_client_on_channel(target_client, channel)) {
2896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2897 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2903 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2907 /* Send command reply to sender */
2908 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2911 /* Send KICKED notify to local clients on the channel */
2912 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
2913 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2914 SILC_NOTIFY_TYPE_KICKED,
2916 idp->data, idp->len,
2917 comment, comment ? strlen(comment) : 0);
2918 silc_buffer_free(idp);
2920 /* Remove the client from the channel. If the channel does not exist
2921 after removing the client then the client kicked itself of the channel
2922 and we don't have to send anything after that. */
2923 if (!silc_server_remove_from_one_channel(server, NULL, channel,
2924 target_client, FALSE))
2927 /* Send KICKED notify to primary route */
2928 if (!server->standalone)
2929 silc_server_send_notify_kicked(server, server->router->connection,
2930 server->server_type == SILC_ROUTER ?
2931 TRUE : FALSE, channel,
2932 target_client->id, SILC_ID_CLIENT_LEN,
2935 /* Re-generate channel key */
2936 silc_server_create_channel_key(server, channel, 0);
2938 /* Send the channel key to the channel. The key of course is not sent
2939 to the client who joined the channel. */
2940 silc_server_send_channel_key(server, target_client->connection, channel,
2941 server->server_type == SILC_ROUTER ?
2942 FALSE : !server->standalone);
2945 silc_server_command_free(cmd);
2948 SILC_SERVER_CMD_FUNC(oper)
2952 SILC_SERVER_CMD_FUNC(silcoper)
2956 /* Server side command of CONNECT. Connects us to the specified remote
2957 server or router. */
2959 SILC_SERVER_CMD_FUNC(connect)
2961 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2962 SilcServer server = cmd->server;
2963 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2965 unsigned int tmp_len;
2966 unsigned int port = SILC_PORT;
2968 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
2970 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2973 /* Check whether client has the permissions. */
2974 if (client->mode == SILC_UMODE_NONE) {
2975 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
2976 SILC_STATUS_ERR_NO_SERVER_PRIV);
2980 if (server->server_type == SILC_ROUTER &&
2981 client->mode & SILC_UMODE_SERVER_OPERATOR) {
2982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
2983 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2987 /* Get the remote server */
2988 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2990 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
2991 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2996 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2998 SILC_GET32_MSB(port, tmp);
3000 /* Create the connection. It is done with timeout and is async. */
3001 silc_server_create_connection(server, tmp, port);
3003 /* Send reply to the sender */
3004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3008 silc_server_command_free(cmd);
3011 SILC_SERVER_CMD_FUNC(restart)
3015 /* Server side command of CLOSE. Closes connection to a specified server. */
3017 SILC_SERVER_CMD_FUNC(close)
3019 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3020 SilcServer server = cmd->server;
3021 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3022 SilcServerEntry server_entry;
3024 unsigned int tmp_len;
3025 unsigned char *name;
3026 unsigned int port = SILC_PORT;
3028 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3030 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3033 /* Check whether client has the permissions. */
3034 if (client->mode == SILC_UMODE_NONE) {
3035 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3036 SILC_STATUS_ERR_NO_SERVER_PRIV);
3040 /* Get the remote server */
3041 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3044 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3049 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3051 SILC_GET32_MSB(port, tmp);
3053 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3055 if (!server_entry) {
3056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3057 SILC_STATUS_ERR_NO_SERVER_ID);
3061 /* Close the connection to the server */
3062 silc_server_free_sock_user_data(server, server_entry->connection);
3063 silc_server_disconnect_remote(server, server_entry->connection,
3064 "Server closed connection: "
3065 "Closed by operator");
3067 /* Send reply to the sender */
3068 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3072 silc_server_command_free(cmd);
3075 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3076 active connections. */
3078 SILC_SERVER_CMD_FUNC(shutdown)
3080 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3081 SilcServer server = cmd->server;
3082 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3084 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3086 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3089 /* Check whether client has the permission. */
3090 if (client->mode == SILC_UMODE_NONE) {
3091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3092 SILC_STATUS_ERR_NO_SERVER_PRIV);
3096 /* Then, gracefully, or not, bring the server down. */
3097 silc_server_stop(server);
3099 /* Send reply to the sender */
3100 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3104 silc_server_command_free(cmd);
3107 /* Server side command of LEAVE. Removes client from a channel. */
3109 SILC_SERVER_CMD_FUNC(leave)
3111 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3112 SilcServer server = cmd->server;
3113 SilcSocketConnection sock = cmd->sock;
3114 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3116 SilcChannelEntry channel;
3118 unsigned int i, len;
3121 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3123 /* Get Channel ID */
3124 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3127 SILC_STATUS_ERR_NO_CHANNEL_ID);
3130 id = silc_id_payload_parse_id(tmp, len);
3132 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3133 SILC_STATUS_ERR_NO_CHANNEL_ID);
3137 /* Get channel entry */
3138 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3140 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3142 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3143 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3148 /* Check whether this client is on the channel */
3149 if (!silc_server_client_on_channel(id_entry, channel)) {
3150 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3151 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3155 /* Notify routers that they should remove this client from their list
3156 of clients on the channel. Send LEAVE notify type. */
3157 if (!server->standalone)
3158 silc_server_send_notify_leave(server, server->router->connection,
3159 server->server_type == SILC_ROUTER ?
3160 TRUE : FALSE, channel, id_entry->id,
3161 SILC_ID_CLIENT_LEN);
3163 /* Remove client from channel */
3164 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3166 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3169 /* If the channel does not exist anymore we won't send anything */
3173 /* Re-generate channel key */
3174 silc_server_create_channel_key(server, channel, 0);
3176 /* Encode channel key payload to be distributed on the channel */
3178 silc_channel_key_payload_encode(len, tmp,
3179 strlen(channel->channel_key->cipher->name),
3180 channel->channel_key->cipher->name,
3181 channel->key_len / 8, channel->key);
3183 /* If we are normal server then we will send it to our router. If we
3184 are router we will send it to all local servers that has clients on
3186 if (server->server_type == SILC_SERVER) {
3187 if (!server->standalone)
3188 silc_server_packet_send(server,
3189 cmd->server->router->connection,
3190 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3191 packet->len, FALSE);
3196 /* Send to locally connected clients on the channel */
3197 silc_server_packet_send_local_channel(server, channel,
3198 SILC_PACKET_CHANNEL_KEY, 0,
3199 packet->data, packet->len, FALSE);
3201 silc_buffer_free(packet);
3205 silc_server_command_free(cmd);
3208 /* Server side of command USERS. Resolves clients and their USERS currently
3209 joined on the requested channel. The list of Client ID's and their modes
3210 on the channel is sent back. */
3212 SILC_SERVER_CMD_FUNC(users)
3214 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3215 SilcServer server = cmd->server;
3216 SilcChannelEntry channel;
3219 unsigned char *channel_id;
3220 unsigned int channel_id_len;
3221 SilcBuffer client_id_list;
3222 SilcBuffer client_mode_list;
3223 unsigned char lc[4];
3224 unsigned int list_count = 0;
3225 unsigned short ident = silc_command_get_ident(cmd->payload);
3227 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3229 /* Get Channel ID */
3230 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3233 SILC_STATUS_ERR_NO_CHANNEL_ID);
3236 id = silc_id_payload_parse_id(channel_id, channel_id_len);
3238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3239 SILC_STATUS_ERR_NO_CHANNEL_ID);
3243 /* If we are server and we don't know about this channel we will send
3244 the command to our router. If we know about the channel then we also
3245 have the list of users already. */
3246 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3248 if (server->server_type == SILC_SERVER && !server->standalone &&
3252 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3253 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3255 /* Send USERS command */
3256 silc_server_packet_send(server, server->router->connection,
3257 SILC_PACKET_COMMAND, cmd->packet->flags,
3258 tmpbuf->data, tmpbuf->len, TRUE);
3260 /* Reprocess this packet after received reply */
3261 silc_server_command_pending(server, SILC_COMMAND_USERS,
3262 silc_command_get_ident(cmd->payload),
3263 silc_server_command_destructor,
3264 silc_server_command_users,
3265 silc_server_command_dup(cmd));
3266 cmd->pending = TRUE;
3267 silc_command_set_ident(cmd->payload, ident);
3269 silc_buffer_free(tmpbuf);
3274 /* We are router and we will check the global list as well. */
3275 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3277 /* Channel really does not exist */
3278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3279 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3284 /* Get the users list */
3285 silc_server_get_users_on_channel(server, channel, &client_id_list,
3286 &client_mode_list, &list_count);
3289 SILC_PUT32_MSB(list_count, lc);
3292 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3293 SILC_STATUS_OK, 0, 4,
3294 2, channel_id, channel_id_len,
3296 4, client_id_list->data,
3297 client_id_list->len,
3298 5, client_mode_list->data,
3299 client_mode_list->len);
3300 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3301 packet->data, packet->len, FALSE);
3303 silc_buffer_free(packet);
3304 silc_buffer_free(client_id_list);
3305 silc_buffer_free(client_mode_list);
3309 silc_server_command_free(cmd);