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 = 4; i < argc + 1; i++) {
397 tmp = silc_argument_get_arg_type(cmd->args, i, &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,
951 SILC_STATUS_OK, ident, 2,
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,
964 SILC_STATUS_OK, ident, 3,
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 /* Create new Client ID */
1285 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1286 cmd->server->md5hash, nick,
1289 /* Send notify about nickname change to our router. We send the new
1290 ID and ask to replace it with the old one. If we are router the
1291 packet is broadcasted. Send NICK_CHANGE notify. */
1292 if (!server->standalone)
1293 silc_server_send_notify_nick_change(server, server->router->connection,
1294 server->server_type == SILC_SERVER ?
1295 FALSE : TRUE, client->id,
1296 new_id, SILC_ID_CLIENT_LEN);
1298 /* Remove old cache entry */
1299 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1302 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1306 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1307 silc_free(client->id);
1310 /* Save the nickname as this client is our local client */
1311 if (client->nickname)
1312 silc_free(client->nickname);
1314 client->nickname = strdup(nick);
1315 client->id = new_id;
1317 /* Update client cache */
1318 silc_idcache_add(server->local_list->clients, client->nickname,
1319 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1321 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1323 /* Send NICK_CHANGE notify to the client's channels */
1324 silc_server_send_notify_on_channels(server, client,
1325 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1326 oidp->data, oidp->len,
1327 nidp->data, nidp->len);
1329 /* Send the new Client ID as reply command back to client */
1330 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1331 SILC_STATUS_OK, 0, 1,
1332 2, nidp->data, nidp->len);
1333 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1334 0, packet->data, packet->len, FALSE);
1336 silc_buffer_free(packet);
1337 silc_buffer_free(nidp);
1338 silc_buffer_free(oidp);
1341 silc_server_command_free(cmd);
1344 SILC_SERVER_CMD_FUNC(list)
1348 /* Server side of TOPIC command. Sets topic for channel and/or returns
1349 current topic to client. */
1351 SILC_SERVER_CMD_FUNC(topic)
1353 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1354 SilcServer server = cmd->server;
1355 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1356 SilcChannelID *channel_id;
1357 SilcChannelEntry channel;
1358 SilcChannelClientEntry chl;
1359 SilcBuffer packet, idp;
1361 unsigned int argc, tmp_len;
1363 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1365 argc = silc_argument_get_arg_num(cmd->args);
1367 /* Get Channel ID */
1368 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1371 SILC_STATUS_ERR_NO_CHANNEL_ID);
1374 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1377 SILC_STATUS_ERR_NO_CHANNEL_ID);
1381 /* Check whether the channel exists */
1382 channel = silc_idlist_find_channel_by_id(server->local_list,
1385 channel = silc_idlist_find_channel_by_id(server->global_list,
1388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1389 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1396 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1398 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1399 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1403 if (strlen(tmp) > 256) {
1404 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1405 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1409 /* See whether has rights to change topic */
1410 silc_list_start(channel->user_list);
1411 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1412 if (chl->client == client)
1415 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1416 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1418 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1423 /* Set the topic for channel */
1425 silc_free(channel->topic);
1426 channel->topic = strdup(tmp);
1428 /* Send TOPIC_SET notify type to the network */
1429 if (!server->standalone)
1430 silc_server_send_notify_topic_set(server, server->router->connection,
1431 server->server_type == SILC_ROUTER ?
1432 TRUE : FALSE, channel, client->id,
1433 SILC_ID_CLIENT_LEN, channel->topic);
1435 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1437 /* Send notify about topic change to all clients on the channel */
1438 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1439 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1440 idp->data, idp->len,
1441 channel->topic, strlen(channel->topic));
1442 silc_buffer_free(idp);
1445 /* Send the topic to client as reply packet */
1446 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1448 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1449 SILC_STATUS_OK, 0, 2,
1450 2, idp->data, idp->len,
1452 strlen(channel->topic));
1454 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1455 SILC_STATUS_OK, 0, 1,
1456 2, idp->data, idp->len);
1457 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1458 0, packet->data, packet->len, FALSE);
1460 silc_buffer_free(packet);
1461 silc_buffer_free(idp);
1462 silc_free(channel_id);
1465 silc_server_command_free(cmd);
1468 /* Server side of INVITE command. Invites some client to join some channel. */
1470 SILC_SERVER_CMD_FUNC(invite)
1472 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1473 SilcServer server = cmd->server;
1474 SilcSocketConnection sock = cmd->sock, dest_sock;
1475 SilcClientEntry sender, dest;
1476 SilcClientID *dest_id;
1477 SilcChannelEntry channel;
1478 SilcChannelID *channel_id;
1483 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1485 /* Get destination ID */
1486 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1489 SILC_STATUS_ERR_NO_CLIENT_ID);
1492 dest_id = silc_id_payload_parse_id(tmp, len);
1494 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1495 SILC_STATUS_ERR_NO_CLIENT_ID);
1499 /* Get Channel ID */
1500 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1502 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1503 SILC_STATUS_ERR_NO_CHANNEL_ID);
1506 channel_id = silc_id_payload_parse_id(tmp, len);
1508 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1509 SILC_STATUS_ERR_NO_CHANNEL_ID);
1513 /* Check whether the channel exists */
1514 channel = silc_idlist_find_channel_by_id(server->local_list,
1517 channel = silc_idlist_find_channel_by_id(server->global_list,
1520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1521 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1526 /* Check whether the sender of this command is on the channel. */
1527 sender = (SilcClientEntry)sock->user_data;
1528 if (!silc_server_client_on_channel(sender, channel)) {
1529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1530 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1534 /* Check whether the channel is invite-only channel. If yes then the
1535 sender of this command must be at least channel operator. */
1536 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1537 SilcChannelClientEntry chl;
1539 silc_list_start(channel->user_list);
1540 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1541 if (chl->client == sender) {
1542 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1543 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1544 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1551 /* Find the connection data for the destination. If it is local we will
1552 send it directly otherwise we will send it to router for routing. */
1553 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1555 dest_sock = (SilcSocketConnection)dest->connection;
1557 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1559 /* Check whether the requested client is already on the channel. */
1560 /* XXX if we are normal server we don't know about global clients on
1561 the channel thus we must request it (USERS command), check from
1562 local cache as well. */
1563 if (silc_server_client_on_channel(dest, channel)) {
1564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1565 SILC_STATUS_ERR_USER_ON_CHANNEL);
1569 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1571 /* Send notify to the client that is invited to the channel */
1572 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1574 SILC_NOTIFY_TYPE_INVITE, 2,
1575 sidp->data, sidp->len, tmp, len);
1577 /* Send command reply */
1578 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1581 silc_buffer_free(sidp);
1584 silc_server_command_free(cmd);
1589 SilcSocketConnection sock;
1593 /* Quits connection to client. This gets called if client won't
1594 close the connection even when it has issued QUIT command. */
1596 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1598 QuitInternal q = (QuitInternal)context;
1600 /* Free all client specific data, such as client entry and entires
1601 on channels this client may be on. */
1602 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1604 q->sock->user_data = NULL;
1606 /* Close the connection on our side */
1607 silc_server_close_connection(q->server, q->sock);
1609 silc_free(q->signoff);
1613 /* Quits SILC session. This is the normal way to disconnect client. */
1615 SILC_SERVER_CMD_FUNC(quit)
1617 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1618 SilcServer server = cmd->server;
1619 SilcSocketConnection sock = cmd->sock;
1621 unsigned char *tmp = NULL;
1622 unsigned int len = 0;
1624 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
1626 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1629 /* Get destination ID */
1630 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1634 q = silc_calloc(1, sizeof(*q));
1637 q->signoff = tmp ? strdup(tmp) : NULL;
1639 /* We quit the connection with little timeout */
1640 silc_task_register(server->timeout_queue, sock->sock,
1641 silc_server_command_quit_cb, (void *)q,
1642 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1645 silc_server_command_free(cmd);
1648 SILC_SERVER_CMD_FUNC(kill)
1652 /* Server side of command INFO. This sends information about us to
1653 the client. If client requested specific server we will send the
1654 command to that server. */
1656 SILC_SERVER_CMD_FUNC(info)
1658 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1659 SilcServer server = cmd->server;
1660 SilcBuffer packet, idp;
1661 char info_string[256], *dest_server;
1663 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1665 /* Get server name */
1666 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1669 SILC_STATUS_ERR_NO_SUCH_SERVER);
1673 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1674 /* Send our reply */
1675 memset(info_string, 0, sizeof(info_string));
1676 snprintf(info_string, sizeof(info_string),
1677 "location: %s server: %s admin: %s <%s>",
1678 server->config->admin_info->location,
1679 server->config->admin_info->server_type,
1680 server->config->admin_info->admin_name,
1681 server->config->admin_info->admin_email);
1683 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1685 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1686 SILC_STATUS_OK, 0, 2,
1687 2, idp->data, idp->len,
1689 strlen(info_string));
1690 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1691 packet->data, packet->len, FALSE);
1693 silc_buffer_free(packet);
1694 silc_buffer_free(idp);
1696 /* Send this command to the requested server */
1698 if (server->server_type == SILC_SERVER && !server->standalone) {
1702 if (server->server_type == SILC_ROUTER) {
1708 silc_server_command_free(cmd);
1711 /* Server side of command PING. This just replies to the ping. */
1713 SILC_SERVER_CMD_FUNC(ping)
1715 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1716 SilcServer server = cmd->server;
1721 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1724 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1726 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1727 SILC_STATUS_ERR_NO_SERVER_ID);
1730 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1734 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1735 /* Send our reply */
1736 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1739 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1740 SILC_STATUS_ERR_NO_SUCH_SERVER);
1747 silc_server_command_free(cmd);
1750 /* Internal routine to join channel. The channel sent to this function
1751 has been either created or resolved from ID lists. This joins the sent
1752 client to the channel. */
1754 static void silc_server_command_join_channel(SilcServer server,
1755 SilcServerCommandContext cmd,
1756 SilcChannelEntry channel,
1757 SilcClientID *client_id,
1761 SilcSocketConnection sock = cmd->sock;
1763 unsigned int tmp_len, user_count;
1764 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
1765 SilcClientEntry client;
1766 SilcChannelClientEntry chl;
1767 SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
1768 unsigned short ident = silc_command_get_ident(cmd->payload);
1770 SILC_LOG_DEBUG(("Start"));
1775 /* Get passphrase */
1776 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1778 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1779 memcpy(passphrase, tmp, tmp_len);
1783 * Check channel modes
1786 /* Check invite list if channel is invite-only channel */
1787 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1788 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1789 /* Invite list is specified. Check whether client is invited in the
1790 list. If not, then check whether it has been invited otherwise. */
1793 /* XXX client must be invited to be able to join the channel */
1797 /* Check ban list if set */
1798 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1802 /* Check the channel passphrase if set. */
1803 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1804 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1805 strlen(channel->mode_data.passphrase))) {
1806 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1807 SILC_STATUS_ERR_BAD_PASSWORD);
1812 /* Check user count limit if set. */
1813 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1814 if (silc_list_count(channel->user_list) + 1 >
1815 channel->mode_data.user_limit) {
1816 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1817 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1823 * Client is allowed to join to the channel. Make it happen.
1826 /* Get the client entry */
1827 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1828 client = (SilcClientEntry)sock->user_data;
1830 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1833 /* XXX actually this is useless since router finds always cell's
1834 local clients from its local lists. */
1835 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1842 /* Check whether the client already is on the channel */
1843 if (silc_server_client_on_channel(client, channel)) {
1844 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1845 SILC_STATUS_ERR_USER_ON_CHANNEL);
1849 /* Generate new channel key as protocol dictates */
1850 if ((!created && silc_list_count(channel->user_list) > 0) ||
1851 !channel->channel_key)
1852 silc_server_create_channel_key(server, channel, 0);
1854 /* Send the channel key. This is broadcasted to the channel but is not
1855 sent to the client who is joining to the channel. */
1856 silc_server_send_channel_key(server, NULL, channel,
1857 server->server_type == SILC_ROUTER ?
1858 FALSE : !server->standalone);
1860 /* Join the client to the channel by adding it to channel's user list.
1861 Add also the channel to client entry's channels list for fast cross-
1863 chl = silc_calloc(1, sizeof(*chl));
1865 chl->client = client;
1866 chl->channel = channel;
1867 silc_list_add(channel->user_list, chl);
1868 silc_list_add(client->channels, chl);
1870 /* Get users on the channel */
1871 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
1874 /* Encode Client ID Payload of the original client who wants to join */
1875 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1877 /* Encode command reply packet */
1878 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1879 SILC_PUT32_MSB(channel->mode, mode);
1880 SILC_PUT32_MSB(created, tmp2);
1881 SILC_PUT32_MSB(user_count, tmp3);
1882 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1883 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1884 strlen(channel->channel_key->
1886 channel->channel_key->cipher->name,
1887 channel->key_len / 8, channel->key);
1889 if (!channel->topic) {
1891 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1892 SILC_STATUS_OK, ident, 9,
1893 2, channel->channel_name,
1894 strlen(channel->channel_name),
1895 3, chidp->data, chidp->len,
1896 4, clidp->data, clidp->len,
1899 7, keyp->data, keyp->len,
1901 13, user_list->data, user_list->len,
1902 14, mode_list->data,
1906 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1907 SILC_STATUS_OK, ident, 10,
1908 2, channel->channel_name,
1909 strlen(channel->channel_name),
1910 3, chidp->data, chidp->len,
1911 4, clidp->data, clidp->len,
1914 7, keyp->data, keyp->len,
1916 strlen(channel->topic),
1918 13, user_list->data, user_list->len,
1919 14, mode_list->data,
1923 /* Send command reply */
1924 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1925 reply->data, reply->len, FALSE);
1927 if (!cmd->pending) {
1928 /* Send JOIN notify to locally connected clients on the channel */
1929 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1930 SILC_NOTIFY_TYPE_JOIN, 2,
1931 clidp->data, clidp->len,
1932 chidp->data, chidp->len);
1934 /* Send JOIN notify packet to our primary router */
1935 if (!server->standalone)
1936 silc_server_send_notify_join(server, server->router->connection,
1937 server->server_type == SILC_ROUTER ?
1938 TRUE : FALSE, channel, client->id,
1939 SILC_ID_CLIENT_LEN);
1942 silc_buffer_free(reply);
1943 silc_buffer_free(clidp);
1944 silc_buffer_free(chidp);
1945 silc_buffer_free(keyp);
1946 silc_buffer_free(user_list);
1947 silc_buffer_free(mode_list);
1951 silc_free(passphrase);
1954 /* Server side of command JOIN. Joins client into requested channel. If
1955 the channel does not exist it will be created. */
1957 SILC_SERVER_CMD_FUNC(join)
1959 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1960 SilcServer server = cmd->server;
1962 char *tmp, *channel_name = NULL, *cipher, *hmac;
1963 SilcChannelEntry channel;
1964 unsigned int umode = 0;
1965 int created = FALSE;
1966 SilcClientID *client_id;
1968 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1970 /* Get channel name */
1971 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1974 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1979 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1980 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1981 SILC_STATUS_ERR_BAD_CHANNEL);
1982 silc_free(channel_name);
1986 /* Get Client ID of the client who is joining to the channel */
1987 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1989 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1990 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1993 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1995 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1996 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2000 /* Get cipher and hmac name */
2001 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2002 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2004 /* See if the channel exists */
2005 channel = silc_idlist_find_channel_by_name(server->local_list,
2006 channel_name, NULL);
2008 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2009 /* If this is coming from client the Client ID in the command packet must
2010 be same as the client's ID. */
2011 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2012 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2013 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2014 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2015 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2021 /* Channel not found */
2023 /* If we are standalone server we don't have a router, we just create
2024 the channel by ourselves. */
2025 if (server->standalone) {
2026 channel = silc_server_create_new_channel(server, server->id, cipher,
2027 hmac, channel_name, TRUE);
2028 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2033 /* The channel does not exist on our server. If we are normal server
2034 we will send JOIN command to our router which will handle the
2035 joining procedure (either creates the channel if it doesn't exist
2036 or joins the client to it). */
2037 if (server->server_type == SILC_SERVER) {
2039 unsigned short old_ident;
2041 old_ident = silc_command_get_ident(cmd->payload);
2042 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2043 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2045 /* Send JOIN command to our router */
2046 silc_server_packet_send(server, (SilcSocketConnection)
2047 server->router->connection,
2048 SILC_PACKET_COMMAND, cmd->packet->flags,
2049 tmpbuf->data, tmpbuf->len, TRUE);
2051 /* Reprocess this packet after received reply from router */
2052 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2053 silc_command_get_ident(cmd->payload),
2054 silc_server_command_destructor,
2055 silc_server_command_join,
2056 silc_server_command_dup(cmd));
2057 cmd->pending = TRUE;
2061 /* We are router and the channel does not seem exist so we will check
2062 our global list as well for the channel. */
2063 channel = silc_idlist_find_channel_by_name(server->global_list,
2064 channel_name, NULL);
2066 /* Channel really does not exist, create it */
2067 channel = silc_server_create_new_channel(server, server->id, cipher,
2068 hmac, channel_name, TRUE);
2069 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2076 /* Channel not found */
2078 /* If the command came from router and/or we are normal server then
2079 something went wrong with the joining as the channel was not found.
2080 We can't do anything else but ignore this. */
2081 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2082 server->server_type == SILC_SERVER)
2085 /* We are router and the channel does not seem exist so we will check
2086 our global list as well for the channel. */
2087 channel = silc_idlist_find_channel_by_name(server->global_list,
2088 channel_name, NULL);
2090 /* Channel really does not exist, create it */
2091 channel = silc_server_create_new_channel(server, server->id, cipher,
2092 hmac, channel_name, TRUE);
2093 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2099 /* If the channel does not have global users and is also empty it means the
2100 channel was created globally (by our router) and the client will be the
2101 channel founder and operator. */
2102 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2103 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2104 created = TRUE; /* Created globally by our router */
2107 /* Join to the channel */
2108 silc_server_command_join_channel(server, cmd, channel, client_id,
2111 silc_free(client_id);
2114 silc_server_command_free(cmd);
2117 /* Server side of command MOTD. Sends server's current "message of the
2118 day" to the client. */
2120 SILC_SERVER_CMD_FUNC(motd)
2122 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2123 SilcServer server = cmd->server;
2127 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2129 /* XXX show currently only our motd */
2131 if (server->config && server->config->motd &&
2132 server->config->motd->motd_file) {
2135 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2140 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2146 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2151 silc_server_command_free(cmd);
2154 SILC_SERVER_CMD_FUNC(umode)
2158 /* Checks that client has rights to add or remove channel modes. If any
2159 of the checks fails FALSE is returned. */
2161 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2162 SilcChannelClientEntry client,
2165 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2166 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2168 /* Check whether has rights to change anything */
2169 if (!is_op && !is_fo)
2172 /* Check whether has rights to change everything */
2176 /* We know that client is channel operator, check that they are not
2177 changing anything that requires channel founder rights. Rest of the
2178 modes are available automatically for channel operator. */
2180 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2181 if (is_op && !is_fo)
2184 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2185 if (is_op && !is_fo)
2190 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2191 if (is_op && !is_fo)
2194 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2195 if (is_op && !is_fo)
2200 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2201 if (is_op && !is_fo)
2204 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2205 if (is_op && !is_fo)
2213 /* Server side command of CMODE. Changes channel mode */
2215 SILC_SERVER_CMD_FUNC(cmode)
2217 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2218 SilcServer server = cmd->server;
2219 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2220 SilcChannelID *channel_id;
2221 SilcChannelEntry channel;
2222 SilcChannelClientEntry chl;
2223 SilcBuffer packet, cidp;
2224 unsigned char *tmp, *tmp_id, *tmp_mask;
2225 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2227 SILC_LOG_DEBUG(("Start"));
2229 argc = silc_argument_get_arg_num(cmd->args);
2231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2232 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2236 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2237 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2241 /* Get Channel ID */
2242 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2245 SILC_STATUS_ERR_NO_CHANNEL_ID);
2248 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2250 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2251 SILC_STATUS_ERR_NO_CHANNEL_ID);
2255 /* Get the channel mode mask */
2256 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2259 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2262 SILC_GET32_MSB(mode_mask, tmp_mask);
2264 /* Get channel entry */
2265 channel = silc_idlist_find_channel_by_id(server->local_list,
2268 channel = silc_idlist_find_channel_by_id(server->global_list,
2271 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2272 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2277 /* Check whether this client is on the channel */
2278 if (!silc_server_client_on_channel(client, channel)) {
2279 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2280 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2284 /* Get entry to the channel user list */
2285 silc_list_start(channel->user_list);
2286 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2287 if (chl->client == client)
2290 /* Check that client has rights to change any requested channel modes */
2291 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2293 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2298 * Check the modes. Modes that requires nothing special operation are
2302 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2303 /* Channel uses private keys to protect traffic. Client(s) has set the
2304 key locally they want to use, server does not know that key. */
2305 /* Nothing interesting to do here now */
2307 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2308 /* The mode is removed and we need to generate and distribute
2309 new channel key. Clients are not using private channel keys
2310 anymore after this. */
2312 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2315 /* Re-generate channel key */
2316 silc_server_create_channel_key(server, channel, 0);
2318 /* Encode channel key payload to be distributed on the channel */
2320 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2321 strlen(channel->channel_key->
2323 channel->channel_key->cipher->name,
2324 channel->key_len / 8, channel->key);
2326 /* If we are normal server then we will send it to our router. If we
2327 are router we will send it to all local servers that has clients on
2329 if (server->server_type == SILC_SERVER) {
2330 if (!server->standalone)
2331 silc_server_packet_send(server,
2332 cmd->server->router->connection,
2333 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2339 /* Send to locally connected clients on the channel */
2340 silc_server_packet_send_local_channel(server, channel,
2341 SILC_PACKET_CHANNEL_KEY, 0,
2342 packet->data, packet->len, FALSE);
2343 silc_buffer_free(packet);
2347 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2348 /* User limit is set on channel */
2349 unsigned int user_limit;
2351 /* Get user limit */
2352 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2354 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2355 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2356 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2360 SILC_GET32_MSB(user_limit, tmp);
2361 channel->mode_data.user_limit = user_limit;
2364 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2365 /* User limit mode is unset. Remove user limit */
2366 channel->mode_data.user_limit = 0;
2369 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2370 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2371 /* Passphrase has been set to channel */
2373 /* Get the passphrase */
2374 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2377 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2381 /* Save the passphrase */
2382 channel->mode_data.passphrase = strdup(tmp);
2385 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2386 /* Passphrase mode is unset. remove the passphrase */
2387 if (channel->mode_data.passphrase) {
2388 silc_free(channel->mode_data.passphrase);
2389 channel->mode_data.passphrase = NULL;
2394 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2395 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2396 /* Ban list is specified for channel */
2399 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2401 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2402 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2406 /* XXX check that channel founder is not banned */
2408 /* Save the ban list */
2409 channel->mode_data.ban_list = strdup(tmp);
2412 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2413 /* Ban mode is unset. Remove the entire ban list */
2414 if (channel->mode_data.ban_list) {
2415 silc_free(channel->mode_data.ban_list);
2416 channel->mode_data.ban_list = NULL;
2421 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2422 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2423 /* Invite list is specified for channel */
2425 /* Get invite list */
2426 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2429 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2433 /* Save the invite linst */
2434 channel->mode_data.invite_list = strdup(tmp);
2437 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2438 /* Invite list mode is unset. Remove the entire invite list */
2439 if (channel->mode_data.invite_list) {
2440 silc_free(channel->mode_data.invite_list);
2441 channel->mode_data.invite_list = NULL;
2446 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2447 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2448 /* Cipher to use protect the traffic */
2449 unsigned int key_len;
2452 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2455 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2459 /* XXX Duplicated code, make own function for this!! */
2461 /* Delete old cipher and allocate the new one */
2462 silc_cipher_free(channel->channel_key);
2463 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
2464 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2465 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2468 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
2470 /* Re-generate channel key */
2471 silc_server_create_channel_key(server, channel, key_len);
2473 /* Encode channel key payload to be distributed on the channel */
2475 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2476 strlen(channel->channel_key->
2478 channel->channel_key->cipher->name,
2479 channel->key_len / 8, channel->key);
2481 /* If we are normal server then we will send it to our router. If we
2482 are router we will send it to all local servers that has clients on
2484 if (server->server_type == SILC_SERVER) {
2485 if (!server->standalone)
2486 silc_server_packet_send(server,
2487 cmd->server->router->connection,
2488 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2494 /* Send to locally connected clients on the channel */
2495 silc_server_packet_send_local_channel(server, channel,
2496 SILC_PACKET_CHANNEL_KEY, 0,
2497 packet->data, packet->len, FALSE);
2498 silc_buffer_free(packet);
2501 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2502 /* Cipher mode is unset. Remove the cipher and revert back to
2505 if (channel->mode_data.cipher) {
2506 silc_free(channel->mode_data.cipher);
2507 channel->mode_data.cipher = NULL;
2508 channel->mode_data.key_len = 0;
2511 /* Generate new cipher and key for the channel */
2513 /* XXX Duplicated code, make own function for this!! */
2515 /* Delete old cipher and allocate default one */
2516 silc_cipher_free(channel->channel_key);
2517 if (!channel->cipher)
2518 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
2520 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
2521 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2522 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2527 /* Re-generate channel key */
2528 silc_server_create_channel_key(server, channel, 0);
2530 /* Encode channel key payload to be distributed on the channel */
2532 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2533 strlen(channel->channel_key->
2535 channel->channel_key->cipher->name,
2536 channel->key_len / 8, channel->key);
2538 /* If we are normal server then we will send it to our router. If we
2539 are router we will send it to all local servers that has clients on
2541 if (server->server_type == SILC_SERVER) {
2542 if (!server->standalone)
2543 silc_server_packet_send(server,
2544 cmd->server->router->connection,
2545 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2551 /* Send to locally connected clients on the channel */
2552 silc_server_packet_send_local_channel(server, channel,
2553 SILC_PACKET_CHANNEL_KEY, 0,
2554 packet->data, packet->len, FALSE);
2555 silc_buffer_free(packet);
2559 /* Finally, set the mode */
2560 channel->mode = mode_mask;
2562 /* Send CMODE_CHANGE notify */
2563 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2564 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2565 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2566 cidp->data, cidp->len,
2569 /* Set CMODE notify type to network */
2570 if (!server->standalone)
2571 silc_server_send_notify_cmode(server, server->router->connection,
2572 server->server_type == SILC_ROUTER ?
2573 TRUE : FALSE, channel,
2574 mode_mask, client->id, SILC_ID_CLIENT_LEN);
2576 /* Send command reply to sender */
2577 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2578 SILC_STATUS_OK, 0, 1,
2580 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2581 packet->data, packet->len, FALSE);
2583 silc_buffer_free(packet);
2584 silc_free(channel_id);
2588 silc_server_command_free(cmd);
2591 /* Server side of CUMODE command. Changes client's mode on a channel. */
2593 SILC_SERVER_CMD_FUNC(cumode)
2595 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2596 SilcServer server = cmd->server;
2597 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2598 SilcChannelID *channel_id;
2599 SilcClientID *client_id;
2600 SilcChannelEntry channel;
2601 SilcClientEntry target_client;
2602 SilcChannelClientEntry chl;
2603 SilcBuffer packet, idp;
2604 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2605 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
2608 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2610 /* Get Channel ID */
2611 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2613 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2614 SILC_STATUS_ERR_NO_CHANNEL_ID);
2617 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
2619 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2620 SILC_STATUS_ERR_NO_CHANNEL_ID);
2624 /* Get channel entry */
2625 channel = silc_idlist_find_channel_by_id(server->local_list,
2628 channel = silc_idlist_find_channel_by_id(server->global_list,
2631 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2632 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2637 /* Check whether sender is on the channel */
2638 if (!silc_server_client_on_channel(client, channel)) {
2639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2640 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2644 /* Check that client has rights to change other's rights */
2645 silc_list_start(channel->user_list);
2646 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2647 if (chl->client == client) {
2648 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2649 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2650 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2651 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2655 sender_mask = chl->mode;
2660 /* Get the target client's channel mode mask */
2661 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2663 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2664 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2667 SILC_GET32_MSB(target_mask, tmp_mask);
2669 /* Get target Client ID */
2670 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2673 SILC_STATUS_ERR_NO_CLIENT_ID);
2676 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2678 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2679 SILC_STATUS_ERR_NO_CLIENT_ID);
2683 /* Get target client's entry */
2684 target_client = silc_idlist_find_client_by_id(server->local_list,
2686 if (!target_client) {
2687 target_client = silc_idlist_find_client_by_id(server->global_list,
2691 /* Check whether target client is on the channel */
2692 if (!silc_server_client_on_channel(target_client, channel)) {
2693 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2694 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2698 /* Get entry to the channel user list */
2699 silc_list_start(channel->user_list);
2700 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2701 if (chl->client == target_client)
2708 /* If the target client is founder, no one else can change their mode
2710 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2712 SILC_STATUS_ERR_NOT_YOU);
2716 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2717 /* Cannot promote anyone to channel founder */
2718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2719 SILC_STATUS_ERR_NOT_YOU);
2722 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2723 if (target_client == client) {
2724 /* Remove channel founder rights from itself */
2725 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2728 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2729 SILC_STATUS_ERR_NOT_YOU);
2735 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2736 /* Promote to operator */
2737 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2738 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2742 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2743 /* Demote to normal user */
2744 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2749 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2751 /* Send notify to channel, notify only if mode was actually changed. */
2753 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2754 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2755 idp->data, idp->len,
2759 /* Set CUMODE notify type to network */
2760 if (!server->standalone)
2761 silc_server_send_notify_cumode(server, server->router->connection,
2762 server->server_type == SILC_ROUTER ?
2763 TRUE : FALSE, channel,
2764 target_mask, client->id,
2767 SILC_ID_CLIENT_LEN);
2770 /* Send command reply to sender */
2771 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2772 SILC_STATUS_OK, 0, 2,
2774 3, tmp_id, tmp_len);
2775 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2776 packet->data, packet->len, FALSE);
2778 silc_buffer_free(packet);
2779 silc_free(channel_id);
2780 silc_free(client_id);
2781 silc_buffer_free(idp);
2784 silc_server_command_free(cmd);
2787 /* Server side of KICK command. Kicks client out of channel. */
2789 SILC_SERVER_CMD_FUNC(kick)
2791 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2792 SilcServer server = cmd->server;
2793 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2794 SilcClientEntry target_client;
2795 SilcChannelID *channel_id;
2796 SilcClientID *client_id;
2797 SilcChannelEntry channel;
2798 SilcChannelClientEntry chl;
2800 unsigned int tmp_len;
2801 unsigned char *tmp, *comment;
2803 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
2805 /* Get Channel ID */
2806 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2808 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2809 SILC_STATUS_ERR_NO_CHANNEL_ID);
2812 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2815 SILC_STATUS_ERR_NO_CHANNEL_ID);
2819 /* Get channel entry */
2820 channel = silc_idlist_find_channel_by_id(server->local_list,
2823 channel = silc_idlist_find_channel_by_id(server->local_list,
2826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2827 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2832 /* Check whether sender is on the channel */
2833 if (!silc_server_client_on_channel(client, channel)) {
2834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2835 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2839 /* Check that the kicker is channel operator or channel founder */
2840 silc_list_start(channel->user_list);
2841 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2842 if (chl->client == client) {
2843 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2844 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2845 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2852 /* Get target Client ID */
2853 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2855 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2856 SILC_STATUS_ERR_NO_CLIENT_ID);
2859 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2862 SILC_STATUS_ERR_NO_CLIENT_ID);
2866 /* Get target client's entry */
2867 target_client = silc_idlist_find_client_by_id(server->local_list,
2869 if (!target_client) {
2870 target_client = silc_idlist_find_client_by_id(server->global_list,
2874 /* Check that the target client is not channel founder. Channel founder
2875 cannot be kicked from the channel. */
2876 silc_list_start(channel->user_list);
2877 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2878 if (chl->client == target_client) {
2879 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2880 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2881 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
2888 /* Check whether target client is on the channel */
2889 if (!silc_server_client_on_channel(target_client, channel)) {
2890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2891 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2897 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2901 /* Send command reply to sender */
2902 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2905 /* Send KICKED notify to local clients on the channel */
2906 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
2907 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2908 SILC_NOTIFY_TYPE_KICKED,
2910 idp->data, idp->len,
2911 comment, comment ? strlen(comment) : 0);
2912 silc_buffer_free(idp);
2914 /* Remove the client from the channel. If the channel does not exist
2915 after removing the client then the client kicked itself of the channel
2916 and we don't have to send anything after that. */
2917 if (!silc_server_remove_from_one_channel(server, NULL, channel,
2918 target_client, FALSE))
2921 /* Send KICKED notify to primary route */
2922 if (!server->standalone)
2923 silc_server_send_notify_kicked(server, server->router->connection,
2924 server->server_type == SILC_ROUTER ?
2925 TRUE : FALSE, channel,
2926 target_client->id, SILC_ID_CLIENT_LEN,
2929 /* Re-generate channel key */
2930 silc_server_create_channel_key(server, channel, 0);
2932 /* Send the channel key to the channel. The key of course is not sent
2933 to the client who joined the channel. */
2934 silc_server_send_channel_key(server, target_client->connection, channel,
2935 server->server_type == SILC_ROUTER ?
2936 FALSE : !server->standalone);
2939 silc_server_command_free(cmd);
2942 SILC_SERVER_CMD_FUNC(oper)
2946 SILC_SERVER_CMD_FUNC(silcoper)
2950 /* Server side command of CONNECT. Connects us to the specified remote
2951 server or router. */
2953 SILC_SERVER_CMD_FUNC(connect)
2955 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2956 SilcServer server = cmd->server;
2957 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2959 unsigned int tmp_len;
2960 unsigned int port = SILC_PORT;
2962 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
2964 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2967 /* Check whether client has the permissions. */
2968 if (client->mode == SILC_UMODE_NONE) {
2969 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
2970 SILC_STATUS_ERR_NO_SERVER_PRIV);
2974 if (server->server_type == SILC_ROUTER &&
2975 client->mode & SILC_UMODE_SERVER_OPERATOR) {
2976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
2977 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2981 /* Get the remote server */
2982 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
2985 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2990 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2992 SILC_GET32_MSB(port, tmp);
2994 /* Create the connection. It is done with timeout and is async. */
2995 silc_server_create_connection(server, tmp, port);
2997 /* Send reply to the sender */
2998 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3002 silc_server_command_free(cmd);
3005 SILC_SERVER_CMD_FUNC(restart)
3009 /* Server side command of CLOSE. Closes connection to a specified server. */
3011 SILC_SERVER_CMD_FUNC(close)
3013 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3014 SilcServer server = cmd->server;
3015 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3016 SilcServerEntry server_entry;
3018 unsigned int tmp_len;
3019 unsigned char *name;
3020 unsigned int port = SILC_PORT;
3022 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3024 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3027 /* Check whether client has the permissions. */
3028 if (client->mode == SILC_UMODE_NONE) {
3029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3030 SILC_STATUS_ERR_NO_SERVER_PRIV);
3034 /* Get the remote server */
3035 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3038 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3043 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3045 SILC_GET32_MSB(port, tmp);
3047 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3049 if (!server_entry) {
3050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3051 SILC_STATUS_ERR_NO_SERVER_ID);
3055 /* Close the connection to the server */
3056 silc_server_free_sock_user_data(server, server_entry->connection);
3057 silc_server_disconnect_remote(server, server_entry->connection,
3058 "Server closed connection: "
3059 "Closed by operator");
3061 /* Send reply to the sender */
3062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3066 silc_server_command_free(cmd);
3069 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3070 active connections. */
3072 SILC_SERVER_CMD_FUNC(shutdown)
3074 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3075 SilcServer server = cmd->server;
3076 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3078 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3080 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3083 /* Check whether client has the permission. */
3084 if (client->mode == SILC_UMODE_NONE) {
3085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3086 SILC_STATUS_ERR_NO_SERVER_PRIV);
3090 /* Then, gracefully, or not, bring the server down. */
3091 silc_server_stop(server);
3093 /* Send reply to the sender */
3094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3098 silc_server_command_free(cmd);
3101 /* Server side command of LEAVE. Removes client from a channel. */
3103 SILC_SERVER_CMD_FUNC(leave)
3105 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3106 SilcServer server = cmd->server;
3107 SilcSocketConnection sock = cmd->sock;
3108 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3110 SilcChannelEntry channel;
3112 unsigned int i, len;
3115 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3117 /* Get Channel ID */
3118 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3121 SILC_STATUS_ERR_NO_CHANNEL_ID);
3124 id = silc_id_payload_parse_id(tmp, len);
3126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3127 SILC_STATUS_ERR_NO_CHANNEL_ID);
3131 /* Get channel entry */
3132 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3134 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3137 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3142 /* Check whether this client is on the channel */
3143 if (!silc_server_client_on_channel(id_entry, channel)) {
3144 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3145 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3149 /* Notify routers that they should remove this client from their list
3150 of clients on the channel. Send LEAVE notify type. */
3151 if (!server->standalone)
3152 silc_server_send_notify_leave(server, server->router->connection,
3153 server->server_type == SILC_ROUTER ?
3154 TRUE : FALSE, channel, id_entry->id,
3155 SILC_ID_CLIENT_LEN);
3157 /* Remove client from channel */
3158 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3160 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3163 /* If the channel does not exist anymore we won't send anything */
3167 /* Re-generate channel key */
3168 silc_server_create_channel_key(server, channel, 0);
3170 /* Encode channel key payload to be distributed on the channel */
3172 silc_channel_key_payload_encode(len, tmp,
3173 strlen(channel->channel_key->cipher->name),
3174 channel->channel_key->cipher->name,
3175 channel->key_len / 8, channel->key);
3177 /* If we are normal server then we will send it to our router. If we
3178 are router we will send it to all local servers that has clients on
3180 if (server->server_type == SILC_SERVER) {
3181 if (!server->standalone)
3182 silc_server_packet_send(server,
3183 cmd->server->router->connection,
3184 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3185 packet->len, FALSE);
3190 /* Send to locally connected clients on the channel */
3191 silc_server_packet_send_local_channel(server, channel,
3192 SILC_PACKET_CHANNEL_KEY, 0,
3193 packet->data, packet->len, FALSE);
3195 silc_buffer_free(packet);
3199 silc_server_command_free(cmd);
3202 /* Server side of command USERS. Resolves clients and their USERS currently
3203 joined on the requested channel. The list of Client ID's and their modes
3204 on the channel is sent back. */
3206 SILC_SERVER_CMD_FUNC(users)
3208 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3209 SilcServer server = cmd->server;
3210 SilcChannelEntry channel;
3213 unsigned char *channel_id;
3214 unsigned int channel_id_len;
3215 SilcBuffer client_id_list;
3216 SilcBuffer client_mode_list;
3217 unsigned char lc[4];
3218 unsigned int list_count = 0;
3219 unsigned short ident = silc_command_get_ident(cmd->payload);
3221 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3223 /* Get Channel ID */
3224 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3226 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3227 SILC_STATUS_ERR_NO_CHANNEL_ID);
3230 id = silc_id_payload_parse_id(channel_id, channel_id_len);
3232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3233 SILC_STATUS_ERR_NO_CHANNEL_ID);
3237 /* If we are server and we don't know about this channel we will send
3238 the command to our router. If we know about the channel then we also
3239 have the list of users already. */
3240 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3242 if (server->server_type == SILC_SERVER && !server->standalone &&
3246 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3247 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3249 /* Send USERS command */
3250 silc_server_packet_send(server, server->router->connection,
3251 SILC_PACKET_COMMAND, cmd->packet->flags,
3252 tmpbuf->data, tmpbuf->len, TRUE);
3254 /* Reprocess this packet after received reply */
3255 silc_server_command_pending(server, SILC_COMMAND_USERS,
3256 silc_command_get_ident(cmd->payload),
3257 silc_server_command_destructor,
3258 silc_server_command_users,
3259 silc_server_command_dup(cmd));
3260 cmd->pending = TRUE;
3261 silc_command_set_ident(cmd->payload, ident);
3263 silc_buffer_free(tmpbuf);
3268 /* We are router and we will check the global list as well. */
3269 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3271 /* Channel really does not exist */
3272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3273 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3278 /* Get the users list */
3279 silc_server_get_users_on_channel(server, channel, &client_id_list,
3280 &client_mode_list, &list_count);
3283 SILC_PUT32_MSB(list_count, lc);
3286 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3287 SILC_STATUS_OK, 0, 4,
3288 2, channel_id, channel_id_len,
3290 4, client_id_list->data,
3291 client_id_list->len,
3292 5, client_mode_list->data,
3293 client_mode_list->len);
3294 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3295 packet->data, packet->len, FALSE);
3297 silc_buffer_free(packet);
3298 silc_buffer_free(client_id_list);
3299 silc_buffer_free(client_mode_list);
3303 silc_server_command_free(cmd);