5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
37 unsigned int arg_type,
39 unsigned int arg_len);
40 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
45 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
49 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
50 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
54 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(connect, CONNECT,
56 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
60 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
63 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
65 SILC_SERVER_CMD(restart, RESTART,
66 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
67 SILC_SERVER_CMD(close, CLOSE,
68 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
69 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
71 SILC_SERVER_CMD(silcoper, SILCOPER,
72 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
73 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
74 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
79 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
81 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
83 SILC_LOG_DEBUG(("Start")); \
86 silc_server_command_send_status_reply(cmd, command, \
87 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
88 silc_server_command_free(cmd); \
92 silc_server_command_send_status_reply(cmd, command, \
93 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
94 silc_server_command_free(cmd); \
99 /* Returns TRUE if the connection is registered. Unregistered connections
100 usually cannot send commands hence the check. */
102 static int silc_server_is_registered(SilcServer server,
103 SilcSocketConnection sock,
104 SilcServerCommandContext cmd,
107 SilcIDListData idata = (SilcIDListData)sock->user_data;
108 if (idata->registered)
111 silc_server_command_send_status_reply(cmd, command,
112 SILC_STATUS_ERR_NOT_REGISTERED);
113 silc_server_command_free(cmd);
117 /* Internal context to hold data when executed command with timeout. */
119 SilcServerCommandContext ctx;
120 SilcServerCommand *cmd;
121 } *SilcServerCommandTimeout;
123 /* Timeout callback to process commands with timeout for client. Client's
124 commands are always executed with timeout. */
126 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
128 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
129 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
131 /* Update access time */
132 client->last_command = time(NULL);
134 if (!(timeout->cmd->flags & SILC_CF_REG))
135 timeout->cmd->cb(timeout->ctx);
136 else if (silc_server_is_registered(timeout->ctx->server,
140 timeout->cmd->cb(timeout->ctx);
145 /* Processes received command packet. */
147 void silc_server_command_process(SilcServer server,
148 SilcSocketConnection sock,
149 SilcPacketContext *packet)
151 SilcServerCommandContext ctx;
152 SilcServerCommand *cmd;
155 /* Allocate command context. This must be free'd by the
156 command routine receiving it. */
157 ctx = silc_server_command_alloc();
158 ctx->server = server;
159 ctx->sock = silc_socket_dup(sock);
160 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
162 /* Parse the command payload in the packet */
163 ctx->payload = silc_command_payload_parse(packet->buffer);
165 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
166 silc_buffer_free(packet->buffer);
167 silc_packet_context_free(packet);
168 silc_socket_free(ctx->sock);
172 ctx->args = silc_command_get_args(ctx->payload);
174 /* Get the command */
175 command = silc_command_get(ctx->payload);
176 for (cmd = silc_command_list; cmd->cb; cmd++)
177 if (cmd->cmd == command)
181 silc_server_command_send_status_reply(ctx, command,
182 SILC_STATUS_ERR_UNKNOWN_COMMAND);
183 silc_server_command_free(ctx);
187 /* Execute client's commands always with timeout. Normally they are
188 executed with zero (0) timeout but if client is sending command more
189 frequently than once in 2 seconds, then the timeout may be 0 to 2
191 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
192 SilcClientEntry client = (SilcClientEntry)sock->user_data;
193 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
199 if (client->last_command && (time(NULL) - client->last_command) < 2) {
200 client->fast_command++;
203 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
204 client->fast_command--);
208 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
209 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
210 silc_task_register(server->timeout_queue, sock->sock,
211 silc_server_command_process_timeout,
213 2 - (time(NULL) - client->last_command), 0,
215 SILC_TASK_PRI_NORMAL);
217 silc_task_register(server->timeout_queue, sock->sock,
218 silc_server_command_process_timeout,
222 SILC_TASK_PRI_NORMAL);
226 /* Execute for server */
228 if (!(cmd->flags & SILC_CF_REG))
230 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
234 /* Allocate Command Context */
236 SilcServerCommandContext silc_server_command_alloc()
238 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
243 /* Free's the command context allocated before executing the command */
245 void silc_server_command_free(SilcServerCommandContext ctx)
248 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
250 if (ctx->users < 1) {
252 silc_command_free_payload(ctx->payload);
254 silc_packet_context_free(ctx->packet);
256 silc_socket_free(ctx->sock); /* Decrease reference counter */
261 /* Duplicate Command Context by adding reference counter. The context won't
262 be free'd untill it hits zero. */
264 SilcServerCommandContext
265 silc_server_command_dup(SilcServerCommandContext ctx)
268 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
273 /* Add new pending command to be executed when reply to a command has been
274 received. The `reply_cmd' is the command that will call the `callback'
275 with `context' when reply has been received. If `ident' is non-zero
276 the `callback' will be executed when received reply with command
277 identifier `ident'. */
279 void silc_server_command_pending(SilcServer server,
280 SilcCommand reply_cmd,
281 unsigned short ident,
282 SilcServerPendingDestructor destructor,
283 SilcCommandCb callback,
286 SilcServerCommandPending *reply;
288 reply = silc_calloc(1, sizeof(*reply));
289 reply->reply_cmd = reply_cmd;
290 reply->ident = ident;
291 reply->context = context;
292 reply->callback = callback;
293 reply->destructor = destructor;
294 silc_dlist_add(server->pending_commands, reply);
297 /* Deletes pending command by reply command type. */
299 void silc_server_command_pending_del(SilcServer server,
300 SilcCommand reply_cmd,
301 unsigned short ident)
303 SilcServerCommandPending *r;
305 silc_dlist_start(server->pending_commands);
306 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
307 if (r->reply_cmd == reply_cmd && r->ident == ident) {
308 silc_dlist_del(server->pending_commands, r);
314 /* Checks for pending commands and marks callbacks to be called from
315 the command reply function. Returns TRUE if there were pending command. */
317 int silc_server_command_pending_check(SilcServer server,
318 SilcServerCommandReplyContext ctx,
320 unsigned short ident)
322 SilcServerCommandPending *r;
324 silc_dlist_start(server->pending_commands);
325 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
326 if (r->reply_cmd == command && r->ident == ident) {
327 ctx->context = r->context;
328 ctx->callback = r->callback;
329 ctx->destructor = r->destructor;
338 /* Destructor function for pending callbacks. This is called when using
339 pending commands to free the context given for the pending command. */
341 static void silc_server_command_destructor(void *context)
343 silc_server_command_free((SilcServerCommandContext)context);
346 /* Sends simple status message as command reply packet */
349 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
351 SilcCommandStatus status)
355 SILC_LOG_DEBUG(("Sending command status %d", status));
358 silc_command_reply_payload_encode_va(command, status,
359 silc_command_get_ident(cmd->payload),
361 silc_server_packet_send(cmd->server, cmd->sock,
362 SILC_PACKET_COMMAND_REPLY, 0,
363 buffer->data, buffer->len, FALSE);
364 silc_buffer_free(buffer);
367 /* Sends command status reply with one extra argument. The argument
368 type must be sent as argument. */
371 silc_server_command_send_status_data(SilcServerCommandContext cmd,
373 SilcCommandStatus status,
374 unsigned int arg_type,
376 unsigned int arg_len)
380 SILC_LOG_DEBUG(("Sending command status %d", status));
383 silc_command_reply_payload_encode_va(command, status,
384 silc_command_get_ident(cmd->payload),
385 1, arg_type, arg, arg_len);
386 silc_server_packet_send(cmd->server, cmd->sock,
387 SILC_PACKET_COMMAND_REPLY, 0,
388 buffer->data, buffer->len, FALSE);
389 silc_buffer_free(buffer);
392 /******************************************************************************
396 ******************************************************************************/
399 silc_server_command_whois_parse(SilcServerCommandContext cmd,
400 SilcClientID ***client_id,
401 unsigned int *client_id_count,
409 unsigned int argc = silc_argument_get_arg_num(cmd->args);
412 /* If client ID is in the command it must be used instead of nickname */
413 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
415 /* No ID, get the nickname@server string and parse it. */
416 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
418 if (strchr(tmp, '@')) {
419 len = strcspn(tmp, "@");
420 *nickname = silc_calloc(len + 1, sizeof(char));
421 memcpy(*nickname, tmp, len);
422 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
423 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
425 *nickname = strdup(tmp);
428 silc_server_command_send_status_reply(cmd, command,
429 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
433 /* Command includes ID, we must use that. Also check whether the command
434 has more than one ID set - take them all. */
436 *client_id = silc_calloc(1, sizeof(**client_id));
437 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
438 if ((*client_id)[0] == NULL) {
439 silc_free(*client_id);
442 *client_id_count = 1;
444 /* Take all ID's from the command packet */
446 for (k = 1, i = 1; i < argc; i++) {
447 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
449 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
450 (*client_id_count + 1));
451 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
452 if ((*client_id)[k] == NULL) {
453 /* Cleanup all and fail */
454 for (i = 0; i < *client_id_count; i++)
455 silc_free((*client_id)[i]);
456 silc_free(*client_id);
459 (*client_id_count)++;
465 /* Command includes ID, use that */
468 /* Get the max count of reply messages allowed */
469 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
479 silc_server_command_whois_check(SilcServerCommandContext cmd,
480 SilcClientEntry *clients,
481 unsigned int clients_count)
483 SilcServer server = cmd->server;
485 SilcClientEntry entry;
487 for (i = 0; i < clients_count; i++) {
490 if (!entry->nickname || !entry->username || !entry->userinfo) {
492 unsigned short old_ident;
497 old_ident = silc_command_get_ident(cmd->payload);
498 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
499 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
501 /* Send WHOIS command */
502 silc_server_packet_send(server, entry->router->connection,
503 SILC_PACKET_COMMAND, cmd->packet->flags,
504 tmpbuf->data, tmpbuf->len, TRUE);
506 /* Reprocess this packet after received reply */
507 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
508 silc_command_get_ident(cmd->payload),
509 silc_server_command_destructor,
510 silc_server_command_whois,
511 silc_server_command_dup(cmd));
514 silc_command_set_ident(cmd->payload, old_ident);
516 silc_buffer_free(tmpbuf);
525 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
526 SilcClientEntry *clients,
527 unsigned int clients_count)
529 SilcServer server = cmd->server;
531 int i, count = 0, len;
532 SilcBuffer packet, idp, channels;
533 SilcClientEntry entry;
534 SilcCommandStatus status;
535 unsigned short ident = silc_command_get_ident(cmd->payload);
536 char nh[128], uh[128];
537 unsigned char idle[4], mode[4];
538 SilcSocketConnection hsock;
540 status = SILC_STATUS_OK;
541 if (clients_count > 1)
542 status = SILC_STATUS_LIST_START;
544 for (i = 0; i < clients_count; i++) {
547 if (entry->connection && entry->data.registered == FALSE) {
548 if (clients_count == 1)
549 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
550 SILC_STATUS_ERR_NO_SUCH_NICK,
552 strlen(entry->nickname));
556 if (count && i - 1 == count)
559 if (clients_count > 2)
560 status = SILC_STATUS_LIST_ITEM;
562 if (clients_count > 1 && i == clients_count - 1)
563 status = SILC_STATUS_LIST_END;
565 /* Sanity check, however these should never fail. However, as
566 this sanity check has been added here they have failed. */
567 if (!entry->nickname || !entry->username || !entry->userinfo)
570 /* Send WHOIS reply */
571 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
572 tmp = silc_argument_get_first_arg(cmd->args, NULL);
574 memset(uh, 0, sizeof(uh));
575 memset(nh, 0, sizeof(nh));
576 memset(idle, 0, sizeof(idle));
578 strncat(nh, entry->nickname, strlen(entry->nickname));
579 if (!strchr(entry->nickname, '@')) {
581 len = entry->router ? strlen(entry->router->server_name) :
582 strlen(server->server_name);
583 strncat(nh, entry->router ? entry->router->server_name :
584 server->server_name, len);
587 strncat(uh, entry->username, strlen(entry->username));
588 if (!strchr(entry->username, '@')) {
590 hsock = (SilcSocketConnection)entry->connection;
591 len = strlen(hsock->hostname);
592 strncat(uh, hsock->hostname, len);
595 channels = silc_server_get_client_channel_list(server, entry);
597 SILC_PUT32_MSB(entry->mode, mode);
599 if (entry->connection) {
600 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
604 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
606 2, idp->data, idp->len,
610 strlen(entry->userinfo),
616 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
618 2, idp->data, idp->len,
622 strlen(entry->userinfo),
626 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
627 0, packet->data, packet->len, FALSE);
629 silc_buffer_free(packet);
630 silc_buffer_free(idp);
632 silc_buffer_free(channels);
637 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
639 SilcServer server = cmd->server;
640 char *nick = NULL, *server_name = NULL;
641 int count = 0, clients_count = 0;
642 SilcClientEntry *clients = NULL, entry;
643 SilcClientID **client_id = NULL;
644 unsigned int client_id_count = 0;
647 /* Protocol dictates that we must always send the received WHOIS request
648 to our router if we are normal server, so let's do it now unless we
649 are standalone. We will not send any replies to the client until we
650 have received reply from the router. */
651 if (server->server_type == SILC_SERVER && !cmd->pending &&
652 !server->standalone) {
654 unsigned short old_ident;
656 old_ident = silc_command_get_ident(cmd->payload);
657 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
658 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
660 /* Send WHOIS command to our router */
661 silc_server_packet_send(server, (SilcSocketConnection)
662 server->router->connection,
663 SILC_PACKET_COMMAND, cmd->packet->flags,
664 tmpbuf->data, tmpbuf->len, TRUE);
666 /* Reprocess this packet after received reply from router */
667 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
668 silc_command_get_ident(cmd->payload),
669 silc_server_command_destructor,
670 silc_server_command_whois,
671 silc_server_command_dup(cmd));
674 silc_command_set_ident(cmd->payload, old_ident);
676 silc_buffer_free(tmpbuf);
681 /* We are ready to process the command request. Let's search for the
682 requested client and send reply to the requesting client. */
684 /* Parse the whois request */
685 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
686 &nick, &server_name, &count,
690 /* Get all clients matching that ID or nickname from local list */
691 if (client_id_count) {
692 /* Check all Client ID's received in the command packet */
693 for (i = 0; i < client_id_count; i++) {
694 entry = silc_idlist_find_client_by_id(server->local_list,
697 clients = silc_realloc(clients, sizeof(*clients) *
698 (clients_count + 1));
699 clients[clients_count++] = entry;
703 clients = silc_idlist_get_clients_by_nickname(server->local_list,
707 clients = silc_idlist_get_clients_by_hash(server->local_list,
708 nick, server->md5hash,
712 /* Check global list as well */
714 if (client_id_count) {
715 /* Check all Client ID's received in the command packet */
716 for (i = 0; i < client_id_count; i++) {
717 entry = silc_idlist_find_client_by_id(server->global_list,
720 clients = silc_realloc(clients, sizeof(*clients) *
721 (clients_count + 1));
722 clients[clients_count++] = entry;
726 clients = silc_idlist_get_clients_by_nickname(server->global_list,
730 clients = silc_idlist_get_clients_by_hash(server->global_list,
731 nick, server->md5hash,
737 /* Such client(s) really does not exist in the SILC network. */
738 if (!client_id_count) {
739 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
740 SILC_STATUS_ERR_NO_SUCH_NICK,
741 3, nick, strlen(nick));
743 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
744 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
745 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
746 2, idp->data, idp->len);
747 silc_buffer_free(idp);
752 /* Router always finds the client entry if it exists in the SILC network.
753 However, it might be incomplete entry and does not include all the
754 mandatory fields that WHOIS command reply requires. Check for these and
755 make query from the server who owns the client if some fields are
757 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
762 /* Send the command reply to the client */
763 silc_server_command_whois_send_reply(cmd, clients, clients_count);
766 if (client_id_count) {
767 for (i = 0; i < client_id_count; i++)
768 silc_free(client_id[i]);
769 silc_free(client_id);
776 silc_free(server_name);
782 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
784 SilcServer server = cmd->server;
785 char *nick = NULL, *server_name = NULL;
786 int count = 0, clients_count = 0;
787 SilcClientEntry *clients = NULL, entry;
788 SilcClientID **client_id = NULL;
789 unsigned int client_id_count = 0;
792 /* Parse the whois request */
793 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
794 &nick, &server_name, &count,
798 /* Process the command request. Let's search for the requested client and
799 send reply to the requesting server. */
801 if (client_id_count) {
802 /* Check all Client ID's received in the command packet */
803 for (i = 0; i < client_id_count; i++) {
804 entry = silc_idlist_find_client_by_id(server->local_list,
807 clients = silc_realloc(clients, sizeof(*clients) *
808 (clients_count + 1));
809 clients[clients_count++] = entry;
813 clients = silc_idlist_get_clients_by_nickname(server->local_list,
817 clients = silc_idlist_get_clients_by_hash(server->local_list,
818 nick, server->md5hash,
822 /* If we are router we will check our global list as well. */
823 if (!clients && server->server_type == SILC_ROUTER) {
824 if (client_id_count) {
825 /* Check all Client ID's received in the command packet */
826 for (i = 0; i < client_id_count; i++) {
827 entry = silc_idlist_find_client_by_id(server->global_list,
830 clients = silc_realloc(clients, sizeof(*clients) *
831 (clients_count + 1));
832 clients[clients_count++] = entry;
836 clients = silc_idlist_get_clients_by_nickname(server->global_list,
840 clients = silc_idlist_get_clients_by_hash(server->global_list,
841 nick, server->md5hash,
847 /* Such a client really does not exist in the SILC network. */
848 if (!client_id_count) {
849 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
850 SILC_STATUS_ERR_NO_SUCH_NICK,
851 3, nick, strlen(nick));
853 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
854 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
855 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
856 2, idp->data, idp->len);
857 silc_buffer_free(idp);
862 /* Router always finds the client entry if it exists in the SILC network.
863 However, it might be incomplete entry and does not include all the
864 mandatory fields that WHOIS command reply requires. Check for these and
865 make query from the server who owns the client if some fields are
867 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
872 /* Send the command reply to the client */
873 silc_server_command_whois_send_reply(cmd, clients, clients_count);
876 if (client_id_count) {
877 for (i = 0; i < client_id_count; i++)
878 silc_free(client_id[i]);
879 silc_free(client_id);
886 silc_free(server_name);
891 /* Server side of command WHOIS. Processes user's query and sends found
892 results as command replies back to the client. */
894 SILC_SERVER_CMD_FUNC(whois)
896 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
899 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
901 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
902 ret = silc_server_command_whois_from_client(cmd);
903 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
904 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
905 ret = silc_server_command_whois_from_server(cmd);
908 silc_server_command_free(cmd);
911 /******************************************************************************
915 ******************************************************************************/
918 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
926 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
928 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
929 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
933 /* Get the nickname@server string and parse it. */
934 if (strchr(tmp, '@')) {
935 len = strcspn(tmp, "@");
936 *nickname = silc_calloc(len + 1, sizeof(char));
937 memcpy(*nickname, tmp, len);
938 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
939 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
941 *nickname = strdup(tmp);
943 /* Get the max count of reply messages allowed */
944 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
954 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
955 SilcClientEntry *clients,
956 unsigned int clients_count)
958 SilcServer server = cmd->server;
960 int i, count = 0, len;
961 SilcBuffer packet, idp;
962 SilcClientEntry entry = NULL;
963 SilcCommandStatus status;
964 unsigned short ident = silc_command_get_ident(cmd->payload);
967 status = SILC_STATUS_OK;
968 if (clients_count > 1)
969 status = SILC_STATUS_LIST_START;
971 for (i = 0; i < clients_count; i++) {
974 /* We will take only clients that are not valid anymore. They are the
975 ones that are not registered anymore but still have a ID. They
976 have disconnected us, and thus valid for WHOWAS. */
977 if (entry->data.registered == TRUE)
979 if (entry->id == NULL)
982 if (count && i - 1 == count)
987 if (clients_count > 2)
988 status = SILC_STATUS_LIST_ITEM;
990 if (clients_count > 1 && i == clients_count - 1)
991 status = SILC_STATUS_LIST_END;
993 /* Sanity check, however these should never fail. However, as
994 this sanity check has been added here they have failed. */
995 if (!entry->nickname || !entry->username)
998 /* Send WHOWAS reply */
999 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1000 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1003 char nh[256], uh[256];
1005 memset(uh, 0, sizeof(uh));
1006 memset(nh, 0, sizeof(nh));
1008 strncat(nh, entry->nickname, strlen(entry->nickname));
1009 if (!strchr(entry->nickname, '@')) {
1010 strncat(nh, "@", 1);
1011 len = entry->router ? strlen(entry->router->server_name) :
1012 strlen(server->server_name);
1013 strncat(nh, entry->router ? entry->router->server_name :
1014 server->server_name, len);
1017 strncat(uh, entry->username, strlen(entry->username));
1018 if (!strchr(entry->username, '@')) {
1019 strncat(uh, "@", 1);
1020 strcat(uh, "*private*");
1024 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1026 2, idp->data, idp->len,
1030 strlen(entry->userinfo));
1033 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1034 0, packet->data, packet->len, FALSE);
1036 silc_buffer_free(packet);
1037 silc_buffer_free(idp);
1040 if (found == FALSE && entry)
1041 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1042 SILC_STATUS_ERR_NO_SUCH_NICK,
1044 strlen(entry->nickname));
1048 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1050 SilcServer server = cmd->server;
1051 char *nick = NULL, *server_name = NULL;
1052 int count = 0, clients_count = 0;
1053 SilcClientEntry *clients = NULL;
1056 /* Protocol dictates that we must always send the received WHOWAS request
1057 to our router if we are normal server, so let's do it now unless we
1058 are standalone. We will not send any replies to the client until we
1059 have received reply from the router. */
1060 if (server->server_type == SILC_SERVER &&
1061 !cmd->pending && !server->standalone) {
1063 unsigned short old_ident;
1065 old_ident = silc_command_get_ident(cmd->payload);
1066 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1067 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1069 /* Send WHOWAS command to our router */
1070 silc_server_packet_send(server, (SilcSocketConnection)
1071 server->router->connection,
1072 SILC_PACKET_COMMAND, cmd->packet->flags,
1073 tmpbuf->data, tmpbuf->len, TRUE);
1075 /* Reprocess this packet after received reply from router */
1076 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1077 silc_command_get_ident(cmd->payload),
1078 silc_server_command_destructor,
1079 silc_server_command_whois,
1080 silc_server_command_dup(cmd));
1081 cmd->pending = TRUE;
1083 silc_command_set_ident(cmd->payload, old_ident);
1085 silc_buffer_free(tmpbuf);
1090 /* We are ready to process the command request. Let's search for the
1091 requested client and send reply to the requesting client. */
1093 /* Parse the whowas request */
1094 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1097 /* Get all clients matching that nickname from local list */
1098 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1102 clients = silc_idlist_get_clients_by_hash(server->local_list,
1103 nick, server->md5hash,
1106 /* Check global list as well */
1108 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1112 clients = silc_idlist_get_clients_by_hash(server->global_list,
1113 nick, server->md5hash,
1118 /* Such client(s) really does not exist in the SILC network. */
1119 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1120 SILC_STATUS_ERR_NO_SUCH_NICK,
1121 3, nick, strlen(nick));
1125 /* Send the command reply to the client */
1126 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1134 silc_free(server_name);
1140 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1142 SilcServer server = cmd->server;
1143 char *nick = NULL, *server_name = NULL;
1144 int count = 0, clients_count = 0;
1145 SilcClientEntry *clients = NULL;
1148 /* Parse the whowas request */
1149 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1152 /* Process the command request. Let's search for the requested client and
1153 send reply to the requesting server. */
1155 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1159 clients = silc_idlist_get_clients_by_hash(server->local_list,
1160 nick, server->md5hash,
1163 /* If we are router we will check our global list as well. */
1164 if (!clients && server->server_type == SILC_ROUTER) {
1165 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1169 clients = silc_idlist_get_clients_by_hash(server->global_list,
1170 nick, server->md5hash,
1175 /* Such a client really does not exist in the SILC network. */
1176 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1177 SILC_STATUS_ERR_NO_SUCH_NICK,
1178 3, nick, strlen(nick));
1182 /* Send the command reply to the client */
1183 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1191 silc_free(server_name);
1196 /* Server side of command WHOWAS. */
1198 SILC_SERVER_CMD_FUNC(whowas)
1200 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1203 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1205 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1206 ret = silc_server_command_whowas_from_client(cmd);
1207 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1208 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1209 ret = silc_server_command_whowas_from_server(cmd);
1212 silc_server_command_free(cmd);
1215 /******************************************************************************
1219 ******************************************************************************/
1221 /* Checks that all mandatory fields are present. If not then send WHOIS
1222 request to the server who owns the client. We use WHOIS because we want
1223 to get as much information as possible at once. */
1226 silc_server_command_identify_check(SilcServerCommandContext cmd,
1227 SilcClientEntry *clients,
1228 unsigned int clients_count)
1230 SilcServer server = cmd->server;
1232 SilcClientEntry entry;
1234 for (i = 0; i < clients_count; i++) {
1237 if (!entry->nickname) {
1239 unsigned short old_ident;
1244 old_ident = silc_command_get_ident(cmd->payload);
1245 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1246 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1247 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1249 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1250 now anyway so make it a good one. */
1251 silc_server_packet_send(server, entry->router->connection,
1252 SILC_PACKET_COMMAND, cmd->packet->flags,
1253 tmpbuf->data, tmpbuf->len, TRUE);
1255 /* Reprocess this packet after received reply */
1256 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1257 silc_command_get_ident(cmd->payload),
1258 silc_server_command_destructor,
1259 silc_server_command_identify,
1260 silc_server_command_dup(cmd));
1262 cmd->pending = TRUE;
1264 /* Put old data back to the Command Payload we just changed */
1265 silc_command_set_ident(cmd->payload, old_ident);
1266 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1268 silc_buffer_free(tmpbuf);
1277 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1278 SilcClientEntry *clients,
1279 unsigned int clients_count)
1281 SilcServer server = cmd->server;
1283 int i, count = 0, len;
1284 SilcBuffer packet, idp;
1285 SilcClientEntry entry;
1286 SilcCommandStatus status;
1287 unsigned short ident = silc_command_get_ident(cmd->payload);
1289 status = SILC_STATUS_OK;
1290 if (clients_count > 1)
1291 status = SILC_STATUS_LIST_START;
1293 for (i = 0; i < clients_count; i++) {
1296 if (entry->connection && entry->data.registered == FALSE) {
1297 if (clients_count == 1)
1298 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1299 SILC_STATUS_ERR_NO_SUCH_NICK,
1301 strlen(entry->nickname));
1305 if (count && i - 1 == count)
1308 if (clients_count > 2)
1309 status = SILC_STATUS_LIST_ITEM;
1311 if (clients_count > 1 && i == clients_count - 1)
1312 status = SILC_STATUS_LIST_END;
1314 /* Send IDENTIFY reply */
1315 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1316 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1320 char nh[256], uh[256];
1321 SilcSocketConnection hsock;
1323 memset(uh, 0, sizeof(uh));
1324 memset(nh, 0, sizeof(nh));
1326 strncat(nh, entry->nickname, strlen(entry->nickname));
1327 if (!strchr(entry->nickname, '@')) {
1328 strncat(nh, "@", 1);
1329 len = entry->router ? strlen(entry->router->server_name) :
1330 strlen(server->server_name);
1331 strncat(nh, entry->router ? entry->router->server_name :
1332 server->server_name, len);
1335 if (!entry->username) {
1336 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1338 2, idp->data, idp->len,
1341 strncat(uh, entry->username, strlen(entry->username));
1342 if (!strchr(entry->username, '@')) {
1343 strncat(uh, "@", 1);
1344 hsock = (SilcSocketConnection)entry->connection;
1345 len = strlen(hsock->hostname);
1346 strncat(uh, hsock->hostname, len);
1349 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1351 2, idp->data, idp->len,
1356 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1357 0, packet->data, packet->len, FALSE);
1359 silc_buffer_free(packet);
1360 silc_buffer_free(idp);
1366 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1368 SilcServer server = cmd->server;
1369 char *nick = NULL, *server_name = NULL;
1370 int count = 0, clients_count = 0;
1371 SilcClientEntry *clients = NULL, entry;
1372 SilcClientID **client_id = NULL;
1373 unsigned int client_id_count = 0;
1376 /* Protocol dictates that we must always send the received IDENTIFY request
1377 to our router if we are normal server, so let's do it now unless we
1378 are standalone. We will not send any replies to the client until we
1379 have received reply from the router. */
1380 if (server->server_type == SILC_SERVER &&
1381 !cmd->pending && !server->standalone) {
1383 unsigned short old_ident;
1385 old_ident = silc_command_get_ident(cmd->payload);
1386 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1387 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1389 /* Send IDENTIFY command to our router */
1390 silc_server_packet_send(server, (SilcSocketConnection)
1391 server->router->connection,
1392 SILC_PACKET_COMMAND, cmd->packet->flags,
1393 tmpbuf->data, tmpbuf->len, TRUE);
1395 /* Reprocess this packet after received reply from router */
1396 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1397 silc_command_get_ident(cmd->payload),
1398 silc_server_command_destructor,
1399 silc_server_command_identify,
1400 silc_server_command_dup(cmd));
1401 cmd->pending = TRUE;
1403 silc_command_set_ident(cmd->payload, old_ident);
1405 silc_buffer_free(tmpbuf);
1410 /* We are ready to process the command request. Let's search for the
1411 requested client and send reply to the requesting client. */
1413 /* Parse the IDENTIFY request */
1414 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1415 &nick, &server_name, &count,
1416 SILC_COMMAND_IDENTIFY))
1419 /* Get all clients matching that ID or nickname from local list */
1420 if (client_id_count) {
1421 /* Check all Client ID's received in the command packet */
1422 for (i = 0; i < client_id_count; i++) {
1423 entry = silc_idlist_find_client_by_id(server->local_list,
1424 client_id[i], NULL);
1426 clients = silc_realloc(clients, sizeof(*clients) *
1427 (clients_count + 1));
1428 clients[clients_count++] = entry;
1432 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1436 clients = silc_idlist_get_clients_by_hash(server->local_list,
1437 nick, server->md5hash,
1441 /* Check global list as well */
1443 if (client_id_count) {
1444 /* Check all Client ID's received in the command packet */
1445 for (i = 0; i < client_id_count; i++) {
1446 entry = silc_idlist_find_client_by_id(server->global_list,
1447 client_id[i], NULL);
1449 clients = silc_realloc(clients, sizeof(*clients) *
1450 (clients_count + 1));
1451 clients[clients_count++] = entry;
1455 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1459 clients = silc_idlist_get_clients_by_hash(server->global_list,
1460 nick, server->md5hash,
1466 /* Such a client really does not exist in the SILC network. */
1467 if (!client_id_count) {
1468 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1469 SILC_STATUS_ERR_NO_SUCH_NICK,
1470 3, nick, strlen(nick));
1472 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1473 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1474 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1475 2, idp->data, idp->len);
1476 silc_buffer_free(idp);
1481 /* Check that all mandatory fields are present and request those data
1482 from the server who owns the client if necessary. */
1483 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1488 /* Send the command reply to the client */
1489 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1492 if (client_id_count) {
1493 for (i = 0; i < client_id_count; i++)
1494 silc_free(client_id[i]);
1495 silc_free(client_id);
1502 silc_free(server_name);
1508 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1510 SilcServer server = cmd->server;
1511 char *nick = NULL, *server_name = NULL;
1512 int count = 0, clients_count = 0;
1513 SilcClientEntry *clients = NULL, entry;
1514 SilcClientID **client_id = NULL;
1515 unsigned int client_id_count = 0;
1518 /* Parse the IDENTIFY request */
1519 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1520 &nick, &server_name, &count,
1521 SILC_COMMAND_IDENTIFY))
1524 /* Process the command request. Let's search for the requested client and
1525 send reply to the requesting server. */
1527 if (client_id_count) {
1528 /* Check all Client ID's received in the command packet */
1529 for (i = 0; i < client_id_count; i++) {
1530 entry = silc_idlist_find_client_by_id(server->local_list,
1531 client_id[i], NULL);
1533 clients = silc_realloc(clients, sizeof(*clients) *
1534 (clients_count + 1));
1535 clients[clients_count++] = entry;
1539 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1543 clients = silc_idlist_get_clients_by_hash(server->local_list,
1544 nick, server->md5hash,
1548 /* If we are router we will check our global list as well. */
1549 if (!clients && server->server_type == SILC_ROUTER) {
1550 if (client_id_count) {
1551 /* Check all Client ID's received in the command packet */
1552 for (i = 0; i < client_id_count; i++) {
1553 entry = silc_idlist_find_client_by_id(server->global_list,
1554 client_id[i], NULL);
1556 clients = silc_realloc(clients, sizeof(*clients) *
1557 (clients_count + 1));
1558 clients[clients_count++] = entry;
1562 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1566 clients = silc_idlist_get_clients_by_hash(server->global_list,
1567 nick, server->md5hash,
1573 /* Such a client really does not exist in the SILC network. */
1574 if (!client_id_count) {
1575 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1576 SILC_STATUS_ERR_NO_SUCH_NICK,
1577 3, nick, strlen(nick));
1579 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1580 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1581 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1582 2, idp->data, idp->len);
1583 silc_buffer_free(idp);
1588 /* Check that all mandatory fields are present and request those data
1589 from the server who owns the client if necessary. */
1590 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1595 /* Send the command reply */
1596 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1599 if (client_id_count) {
1600 for (i = 0; i < client_id_count; i++)
1601 silc_free(client_id[i]);
1602 silc_free(client_id);
1609 silc_free(server_name);
1614 SILC_SERVER_CMD_FUNC(identify)
1616 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1619 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1621 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1622 ret = silc_server_command_identify_from_client(cmd);
1623 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1624 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1625 ret = silc_server_command_identify_from_server(cmd);
1628 silc_server_command_free(cmd);
1631 /* Checks string for bad characters and returns TRUE if they are found. */
1633 static int silc_server_command_bad_chars(char *nick)
1635 if (strchr(nick, '\\')) return TRUE;
1636 if (strchr(nick, '\"')) return TRUE;
1637 if (strchr(nick, '´')) return TRUE;
1638 if (strchr(nick, '`')) return TRUE;
1639 if (strchr(nick, '\'')) return TRUE;
1640 if (strchr(nick, '*')) return TRUE;
1641 if (strchr(nick, '/')) return TRUE;
1642 if (strchr(nick, '@')) return TRUE;
1647 /* Server side of command NICK. Sets nickname for user. Setting
1648 nickname causes generation of a new client ID for the client. The
1649 new client ID is sent to the client after changing the nickname. */
1651 SILC_SERVER_CMD_FUNC(nick)
1653 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1654 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1655 SilcServer server = cmd->server;
1656 SilcBuffer packet, nidp, oidp;
1657 SilcClientID *new_id;
1659 unsigned short ident = silc_command_get_ident(cmd->payload);
1661 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1664 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1666 /* Check nickname */
1667 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1668 if (silc_server_command_bad_chars(nick) == TRUE) {
1669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1670 SILC_STATUS_ERR_BAD_NICKNAME);
1674 if (strlen(nick) > 128)
1677 /* Create new Client ID */
1678 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1679 cmd->server->md5hash, nick,
1682 /* Send notify about nickname change to our router. We send the new
1683 ID and ask to replace it with the old one. If we are router the
1684 packet is broadcasted. Send NICK_CHANGE notify. */
1685 if (!server->standalone)
1686 silc_server_send_notify_nick_change(server, server->router->connection,
1687 server->server_type == SILC_SERVER ?
1688 FALSE : TRUE, client->id,
1689 new_id, SILC_ID_CLIENT_LEN);
1691 /* Remove old cache entry */
1692 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1695 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1699 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1700 silc_free(client->id);
1703 /* Save the nickname as this client is our local client */
1704 if (client->nickname)
1705 silc_free(client->nickname);
1707 client->nickname = strdup(nick);
1708 client->id = new_id;
1710 /* Update client cache */
1711 silc_idcache_add(server->local_list->clients, client->nickname,
1712 SILC_ID_CLIENT, client->id, (void *)client, TRUE, FALSE);
1714 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1716 /* Send NICK_CHANGE notify to the client's channels */
1717 silc_server_send_notify_on_channels(server, NULL, client,
1718 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1719 oidp->data, oidp->len,
1720 nidp->data, nidp->len);
1722 /* Send the new Client ID as reply command back to client */
1723 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1724 SILC_STATUS_OK, ident, 1,
1725 2, nidp->data, nidp->len);
1726 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1727 0, packet->data, packet->len, FALSE);
1729 silc_buffer_free(packet);
1730 silc_buffer_free(nidp);
1731 silc_buffer_free(oidp);
1734 silc_server_command_free(cmd);
1737 SILC_SERVER_CMD_FUNC(list)
1741 /* Server side of TOPIC command. Sets topic for channel and/or returns
1742 current topic to client. */
1744 SILC_SERVER_CMD_FUNC(topic)
1746 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1747 SilcServer server = cmd->server;
1748 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1749 SilcChannelID *channel_id;
1750 SilcChannelEntry channel;
1751 SilcChannelClientEntry chl;
1752 SilcBuffer packet, idp;
1754 unsigned int argc, tmp_len;
1755 unsigned short ident = silc_command_get_ident(cmd->payload);
1757 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1759 argc = silc_argument_get_arg_num(cmd->args);
1761 /* Get Channel ID */
1762 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1764 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1765 SILC_STATUS_ERR_NO_CHANNEL_ID);
1768 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1770 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1771 SILC_STATUS_ERR_NO_CHANNEL_ID);
1775 /* Check whether the channel exists */
1776 channel = silc_idlist_find_channel_by_id(server->local_list,
1779 channel = silc_idlist_find_channel_by_id(server->global_list,
1782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1783 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1790 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1792 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1793 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1797 if (strlen(tmp) > 256) {
1798 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1799 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1803 /* See whether has rights to change topic */
1804 silc_list_start(channel->user_list);
1805 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1806 if (chl->client == client)
1809 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1810 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1812 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1817 /* Set the topic for channel */
1819 silc_free(channel->topic);
1820 channel->topic = strdup(tmp);
1822 /* Send TOPIC_SET notify type to the network */
1823 if (!server->standalone)
1824 silc_server_send_notify_topic_set(server, server->router->connection,
1825 server->server_type == SILC_ROUTER ?
1826 TRUE : FALSE, channel, client->id,
1827 SILC_ID_CLIENT_LEN, channel->topic);
1829 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1831 /* Send notify about topic change to all clients on the channel */
1832 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1833 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1834 idp->data, idp->len,
1835 channel->topic, strlen(channel->topic));
1836 silc_buffer_free(idp);
1839 /* Send the topic to client as reply packet */
1840 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1842 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1843 SILC_STATUS_OK, ident, 2,
1844 2, idp->data, idp->len,
1846 strlen(channel->topic));
1848 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1849 SILC_STATUS_OK, ident, 1,
1850 2, idp->data, idp->len);
1851 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1852 0, packet->data, packet->len, FALSE);
1854 silc_buffer_free(packet);
1855 silc_buffer_free(idp);
1856 silc_free(channel_id);
1859 silc_server_command_free(cmd);
1862 /* Server side of INVITE command. Invites some client to join some channel. */
1864 SILC_SERVER_CMD_FUNC(invite)
1866 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1867 SilcServer server = cmd->server;
1868 SilcSocketConnection sock = cmd->sock, dest_sock;
1869 SilcClientEntry sender, dest;
1870 SilcClientID *dest_id;
1871 SilcChannelEntry channel;
1872 SilcChannelID *channel_id;
1877 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1879 /* Get destination ID */
1880 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1883 SILC_STATUS_ERR_NO_CLIENT_ID);
1886 dest_id = silc_id_payload_parse_id(tmp, len);
1888 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1889 SILC_STATUS_ERR_NO_CLIENT_ID);
1893 /* Get Channel ID */
1894 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1897 SILC_STATUS_ERR_NO_CHANNEL_ID);
1900 channel_id = silc_id_payload_parse_id(tmp, len);
1902 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1903 SILC_STATUS_ERR_NO_CHANNEL_ID);
1907 /* Check whether the channel exists */
1908 channel = silc_idlist_find_channel_by_id(server->local_list,
1911 channel = silc_idlist_find_channel_by_id(server->global_list,
1914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1915 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1920 /* Check whether the sender of this command is on the channel. */
1921 sender = (SilcClientEntry)sock->user_data;
1922 if (!silc_server_client_on_channel(sender, channel)) {
1923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1924 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1928 /* Check whether the channel is invite-only channel. If yes then the
1929 sender of this command must be at least channel operator. */
1930 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1931 SilcChannelClientEntry chl;
1933 silc_list_start(channel->user_list);
1934 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1935 if (chl->client == sender) {
1936 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1937 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1938 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1945 /* Find the connection data for the destination. If it is local we will
1946 send it directly otherwise we will send it to router for routing. */
1947 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1949 dest_sock = (SilcSocketConnection)dest->connection;
1951 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1953 /* Check whether the requested client is already on the channel. */
1954 /* XXX if we are normal server we don't know about global clients on
1955 the channel thus we must request it (USERS command), check from
1956 local cache as well. */
1957 if (silc_server_client_on_channel(dest, channel)) {
1958 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1959 SILC_STATUS_ERR_USER_ON_CHANNEL);
1963 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1965 /* Send notify to the client that is invited to the channel */
1966 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1968 SILC_NOTIFY_TYPE_INVITE, 2,
1969 sidp->data, sidp->len, tmp, len);
1971 /* Send command reply */
1972 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1975 silc_buffer_free(sidp);
1978 silc_server_command_free(cmd);
1983 SilcSocketConnection sock;
1987 /* Quits connection to client. This gets called if client won't
1988 close the connection even when it has issued QUIT command. */
1990 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1992 QuitInternal q = (QuitInternal)context;
1994 /* Free all client specific data, such as client entry and entires
1995 on channels this client may be on. */
1996 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1998 q->sock->user_data = NULL;
2000 /* Close the connection on our side */
2001 silc_server_close_connection(q->server, q->sock);
2003 silc_free(q->signoff);
2007 /* Quits SILC session. This is the normal way to disconnect client. */
2009 SILC_SERVER_CMD_FUNC(quit)
2011 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2012 SilcServer server = cmd->server;
2013 SilcSocketConnection sock = cmd->sock;
2015 unsigned char *tmp = NULL;
2016 unsigned int len = 0;
2018 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2020 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2023 /* Get destination ID */
2024 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2028 q = silc_calloc(1, sizeof(*q));
2031 q->signoff = tmp ? strdup(tmp) : NULL;
2033 /* We quit the connection with little timeout */
2034 silc_task_register(server->timeout_queue, sock->sock,
2035 silc_server_command_quit_cb, (void *)q,
2036 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2039 silc_server_command_free(cmd);
2042 /* Server side of command KILL. This command is used by router operator
2043 to remove an client from the SILC Network temporarily. */
2045 SILC_SERVER_CMD_FUNC(kill)
2047 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2048 SilcServer server = cmd->server;
2049 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2050 SilcClientEntry remote_client;
2051 SilcClientID *client_id;
2052 unsigned char *tmp, *comment;
2053 unsigned int tmp_len, tmp_len2;
2055 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2057 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2060 /* KILL command works only on router */
2061 if (server->server_type != SILC_ROUTER) {
2062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2063 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2067 /* Check whether client has the permissions. */
2068 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2069 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2070 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2074 /* Get the client ID */
2075 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2077 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2078 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2081 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2083 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2084 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2088 /* Get the client entry */
2089 remote_client = silc_idlist_find_client_by_id(server->local_list,
2091 if (!remote_client) {
2092 remote_client = silc_idlist_find_client_by_id(server->global_list,
2094 if (!remote_client) {
2095 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2096 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2102 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2106 /* Send reply to the sender */
2107 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2110 /* Send the KILL notify packets. First send it to the channel, then
2111 to our primary router and then directly to the client who is being
2112 killed right now. */
2114 /* Send KILLED notify to the channels. It is not sent to the client
2115 as it will be sent differently destined directly to the client and not
2117 silc_server_send_notify_on_channels(server, remote_client,
2118 remote_client, SILC_NOTIFY_TYPE_KILLED,
2121 comment, comment ? tmp_len2 : 0);
2123 /* Send KILLED notify to primary route */
2124 if (!server->standalone)
2125 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2126 remote_client->id, SILC_ID_CLIENT_LEN,
2129 /* Send KILLED notify to the client directly */
2130 silc_server_send_notify_killed(server, remote_client->connection ?
2131 remote_client->connection :
2132 remote_client->router->connection, FALSE,
2133 remote_client->id, SILC_ID_CLIENT_LEN,
2136 /* Remove the client from all channels. This generates new keys to the
2137 channels as well. */
2138 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2141 /* Remove the client entry, If it is locally connected then we will also
2142 disconnect the client here */
2143 if (remote_client->data.registered && remote_client->connection) {
2144 /* Remove locally conneted client */
2145 SilcSocketConnection sock = remote_client->connection;
2146 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2147 silc_server_close_connection(server, sock);
2149 /* Remove remote client */
2150 if (!silc_idlist_del_client(server->global_list, remote_client))
2151 silc_idlist_del_client(server->local_list, remote_client);
2155 silc_server_command_free(cmd);
2158 /* Server side of command INFO. This sends information about us to
2159 the client. If client requested specific server we will send the
2160 command to that server. */
2162 SILC_SERVER_CMD_FUNC(info)
2164 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2165 SilcServer server = cmd->server;
2166 SilcBuffer packet, idp;
2167 char info_string[256], *dest_server;
2169 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
2171 /* Get server name */
2172 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2174 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2175 SILC_STATUS_ERR_NO_SUCH_SERVER);
2179 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2180 /* Send our reply */
2181 memset(info_string, 0, sizeof(info_string));
2182 snprintf(info_string, sizeof(info_string),
2183 "location: %s server: %s admin: %s <%s>",
2184 server->config->admin_info->location,
2185 server->config->admin_info->server_type,
2186 server->config->admin_info->admin_name,
2187 server->config->admin_info->admin_email);
2189 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2191 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2192 SILC_STATUS_OK, 0, 2,
2193 2, idp->data, idp->len,
2195 strlen(info_string));
2196 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2197 packet->data, packet->len, FALSE);
2199 silc_buffer_free(packet);
2200 silc_buffer_free(idp);
2202 /* Send this command to the requested server */
2204 if (server->server_type == SILC_SERVER && !server->standalone) {
2208 if (server->server_type == SILC_ROUTER) {
2214 silc_server_command_free(cmd);
2217 /* Server side of command PING. This just replies to the ping. */
2219 SILC_SERVER_CMD_FUNC(ping)
2221 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2222 SilcServer server = cmd->server;
2227 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2230 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2233 SILC_STATUS_ERR_NO_SERVER_ID);
2236 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2240 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2241 /* Send our reply */
2242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2245 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2246 SILC_STATUS_ERR_NO_SUCH_SERVER);
2253 silc_server_command_free(cmd);
2256 /* Internal routine to join channel. The channel sent to this function
2257 has been either created or resolved from ID lists. This joins the sent
2258 client to the channel. */
2260 static void silc_server_command_join_channel(SilcServer server,
2261 SilcServerCommandContext cmd,
2262 SilcChannelEntry channel,
2263 SilcClientID *client_id,
2267 SilcSocketConnection sock = cmd->sock;
2269 unsigned int tmp_len, user_count;
2270 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2271 SilcClientEntry client;
2272 SilcChannelClientEntry chl;
2273 SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
2274 unsigned short ident = silc_command_get_ident(cmd->payload);
2276 SILC_LOG_DEBUG(("Start"));
2281 /* Get passphrase */
2282 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2284 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2285 memcpy(passphrase, tmp, tmp_len);
2289 * Check channel modes
2292 /* Check invite list if channel is invite-only channel */
2293 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2294 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2295 /* Invite list is specified. Check whether client is invited in the
2296 list. If not, then check whether it has been invited otherwise. */
2299 /* XXX client must be invited to be able to join the channel */
2303 /* Check ban list if set */
2304 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2308 /* Check the channel passphrase if set. */
2309 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2310 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
2311 strlen(channel->mode_data.passphrase))) {
2312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2313 SILC_STATUS_ERR_BAD_PASSWORD);
2318 /* Check user count limit if set. */
2319 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2320 if (silc_list_count(channel->user_list) + 1 >
2321 channel->mode_data.user_limit) {
2322 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2323 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2329 * Client is allowed to join to the channel. Make it happen.
2332 /* Get the client entry */
2333 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2334 client = (SilcClientEntry)sock->user_data;
2336 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2339 /* XXX actually this is useless since router finds always cell's
2340 local clients from its local lists. */
2341 client = silc_idlist_find_client_by_id(server->global_list, client_id,
2348 /* Check whether the client already is on the channel */
2349 if (silc_server_client_on_channel(client, channel)) {
2350 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2351 SILC_STATUS_ERR_USER_ON_CHANNEL);
2355 /* Generate new channel key as protocol dictates */
2356 if ((!created && silc_list_count(channel->user_list) > 0) ||
2357 !channel->channel_key)
2358 silc_server_create_channel_key(server, channel, 0);
2360 /* Send the channel key. This is broadcasted to the channel but is not
2361 sent to the client who is joining to the channel. */
2362 silc_server_send_channel_key(server, NULL, channel,
2363 server->server_type == SILC_ROUTER ?
2364 FALSE : !server->standalone);
2366 /* Join the client to the channel by adding it to channel's user list.
2367 Add also the channel to client entry's channels list for fast cross-
2369 chl = silc_calloc(1, sizeof(*chl));
2371 chl->client = client;
2372 chl->channel = channel;
2373 silc_list_add(channel->user_list, chl);
2374 silc_list_add(client->channels, chl);
2376 /* Get users on the channel */
2377 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2380 /* Encode Client ID Payload of the original client who wants to join */
2381 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2383 /* Encode command reply packet */
2384 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2385 SILC_PUT32_MSB(channel->mode, mode);
2386 SILC_PUT32_MSB(created, tmp2);
2387 SILC_PUT32_MSB(user_count, tmp3);
2388 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2389 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2390 strlen(channel->channel_key->
2392 channel->channel_key->cipher->name,
2393 channel->key_len / 8, channel->key);
2395 if (!channel->topic) {
2397 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2398 SILC_STATUS_OK, ident, 9,
2399 2, channel->channel_name,
2400 strlen(channel->channel_name),
2401 3, chidp->data, chidp->len,
2402 4, clidp->data, clidp->len,
2405 7, keyp->data, keyp->len,
2407 13, user_list->data, user_list->len,
2408 14, mode_list->data,
2412 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2413 SILC_STATUS_OK, ident, 10,
2414 2, channel->channel_name,
2415 strlen(channel->channel_name),
2416 3, chidp->data, chidp->len,
2417 4, clidp->data, clidp->len,
2420 7, keyp->data, keyp->len,
2422 strlen(channel->topic),
2424 13, user_list->data, user_list->len,
2425 14, mode_list->data,
2429 /* Send command reply */
2430 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2431 reply->data, reply->len, FALSE);
2433 if (!cmd->pending) {
2434 /* Send JOIN notify to locally connected clients on the channel */
2435 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2436 SILC_NOTIFY_TYPE_JOIN, 2,
2437 clidp->data, clidp->len,
2438 chidp->data, chidp->len);
2440 /* Send JOIN notify packet to our primary router */
2441 if (!server->standalone)
2442 silc_server_send_notify_join(server, server->router->connection,
2443 server->server_type == SILC_ROUTER ?
2444 TRUE : FALSE, channel, client->id,
2445 SILC_ID_CLIENT_LEN);
2448 silc_buffer_free(reply);
2449 silc_buffer_free(clidp);
2450 silc_buffer_free(chidp);
2451 silc_buffer_free(keyp);
2452 silc_buffer_free(user_list);
2453 silc_buffer_free(mode_list);
2457 silc_free(passphrase);
2460 /* Server side of command JOIN. Joins client into requested channel. If
2461 the channel does not exist it will be created. */
2463 SILC_SERVER_CMD_FUNC(join)
2465 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2466 SilcServer server = cmd->server;
2468 char *tmp, *channel_name = NULL, *cipher, *hmac;
2469 SilcChannelEntry channel;
2470 unsigned int umode = 0;
2471 int created = FALSE;
2472 SilcClientID *client_id;
2474 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2476 /* Get channel name */
2477 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2480 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2485 if (strlen(channel_name) > 256)
2486 channel_name[255] = '\0';
2488 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2489 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2490 SILC_STATUS_ERR_BAD_CHANNEL);
2491 silc_free(channel_name);
2495 /* Get Client ID of the client who is joining to the channel */
2496 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2498 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2499 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2502 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2505 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2509 /* Get cipher and hmac name */
2510 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2511 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2513 /* See if the channel exists */
2514 channel = silc_idlist_find_channel_by_name(server->local_list,
2515 channel_name, NULL);
2517 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2518 /* If this is coming from client the Client ID in the command packet must
2519 be same as the client's ID. */
2520 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2521 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2522 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2523 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2524 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2530 /* Channel not found */
2532 /* If we are standalone server we don't have a router, we just create
2533 the channel by ourselves. */
2534 if (server->standalone) {
2535 channel = silc_server_create_new_channel(server, server->id, cipher,
2536 hmac, channel_name, TRUE);
2537 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2542 /* The channel does not exist on our server. If we are normal server
2543 we will send JOIN command to our router which will handle the
2544 joining procedure (either creates the channel if it doesn't exist
2545 or joins the client to it). */
2546 if (server->server_type == SILC_SERVER) {
2548 unsigned short old_ident;
2550 old_ident = silc_command_get_ident(cmd->payload);
2551 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2552 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2554 /* Send JOIN command to our router */
2555 silc_server_packet_send(server, (SilcSocketConnection)
2556 server->router->connection,
2557 SILC_PACKET_COMMAND, cmd->packet->flags,
2558 tmpbuf->data, tmpbuf->len, TRUE);
2560 /* Reprocess this packet after received reply from router */
2561 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2562 silc_command_get_ident(cmd->payload),
2563 silc_server_command_destructor,
2564 silc_server_command_join,
2565 silc_server_command_dup(cmd));
2566 cmd->pending = TRUE;
2570 /* We are router and the channel does not seem exist so we will check
2571 our global list as well for the channel. */
2572 channel = silc_idlist_find_channel_by_name(server->global_list,
2573 channel_name, NULL);
2575 /* Channel really does not exist, create it */
2576 channel = silc_server_create_new_channel(server, server->id, cipher,
2577 hmac, channel_name, TRUE);
2578 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2585 /* Channel not found */
2587 /* If the command came from router and/or we are normal server then
2588 something went wrong with the joining as the channel was not found.
2589 We can't do anything else but ignore this. */
2590 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2591 server->server_type == SILC_SERVER)
2594 /* We are router and the channel does not seem exist so we will check
2595 our global list as well for the channel. */
2596 channel = silc_idlist_find_channel_by_name(server->global_list,
2597 channel_name, NULL);
2599 /* Channel really does not exist, create it */
2600 channel = silc_server_create_new_channel(server, server->id, cipher,
2601 hmac, channel_name, TRUE);
2602 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2608 /* If the channel does not have global users and is also empty it means the
2609 channel was created globally (by our router) and the client will be the
2610 channel founder and operator. */
2611 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2612 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2613 created = TRUE; /* Created globally by our router */
2616 /* Join to the channel */
2617 silc_server_command_join_channel(server, cmd, channel, client_id,
2620 silc_free(client_id);
2623 silc_server_command_free(cmd);
2626 /* Server side of command MOTD. Sends server's current "message of the
2627 day" to the client. */
2629 SILC_SERVER_CMD_FUNC(motd)
2631 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2632 SilcServer server = cmd->server;
2636 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2638 /* XXX show currently only our motd */
2640 if (server->config && server->config->motd &&
2641 server->config->motd->motd_file) {
2644 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2649 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2660 silc_server_command_free(cmd);
2663 /* Server side of command UMODE. Client can use this command to set/unset
2664 user mode. Client actually cannot set itself to be as server/router
2665 operator so this can be used only to unset the modes. */
2667 SILC_SERVER_CMD_FUNC(umode)
2669 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2670 SilcServer server = cmd->server;
2671 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2673 unsigned char *tmp_mask;
2675 unsigned short ident = silc_command_get_ident(cmd->payload);
2677 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2680 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
2682 /* Get the client's mode mask */
2683 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2685 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2686 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2689 SILC_GET32_MSB(mask, tmp_mask);
2695 if (mask & SILC_UMODE_SERVER_OPERATOR) {
2696 /* Cannot operator mode */
2697 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2698 SILC_STATUS_ERR_PERM_DENIED);
2701 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
2702 /* Remove the server operator rights */
2703 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
2706 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
2707 /* Cannot operator mode */
2708 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2709 SILC_STATUS_ERR_PERM_DENIED);
2712 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
2713 /* Remove the router operator rights */
2714 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
2717 /* Send UMODE change to primary router */
2718 if (!server->standalone)
2719 silc_server_send_notify_umode(server, server->router->connection, TRUE,
2720 client->id, SILC_ID_CLIENT_LEN,
2723 /* Send command reply to sender */
2724 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
2725 SILC_STATUS_OK, ident, 1,
2727 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2728 packet->data, packet->len, FALSE);
2729 silc_buffer_free(packet);
2732 silc_server_command_free(cmd);
2735 /* Checks that client has rights to add or remove channel modes. If any
2736 of the checks fails FALSE is returned. */
2738 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2739 SilcChannelClientEntry client,
2742 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2743 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2745 /* Check whether has rights to change anything */
2746 if (!is_op && !is_fo)
2749 /* Check whether has rights to change everything */
2753 /* We know that client is channel operator, check that they are not
2754 changing anything that requires channel founder rights. Rest of the
2755 modes are available automatically for channel operator. */
2757 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2758 if (is_op && !is_fo)
2761 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2762 if (is_op && !is_fo)
2767 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2768 if (is_op && !is_fo)
2771 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2772 if (is_op && !is_fo)
2777 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2778 if (is_op && !is_fo)
2781 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2782 if (is_op && !is_fo)
2790 /* Server side command of CMODE. Changes channel mode */
2792 SILC_SERVER_CMD_FUNC(cmode)
2794 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2795 SilcServer server = cmd->server;
2796 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2797 SilcChannelID *channel_id;
2798 SilcChannelEntry channel;
2799 SilcChannelClientEntry chl;
2800 SilcBuffer packet, cidp;
2801 unsigned char *tmp, *tmp_id, *tmp_mask;
2802 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2803 unsigned short ident = silc_command_get_ident(cmd->payload);
2805 SILC_LOG_DEBUG(("Start"));
2807 argc = silc_argument_get_arg_num(cmd->args);
2809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2810 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2815 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2819 /* Get Channel ID */
2820 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2823 SILC_STATUS_ERR_NO_CHANNEL_ID);
2826 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2829 SILC_STATUS_ERR_NO_CHANNEL_ID);
2833 /* Get the channel mode mask */
2834 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2837 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2840 SILC_GET32_MSB(mode_mask, tmp_mask);
2842 /* Get channel entry */
2843 channel = silc_idlist_find_channel_by_id(server->local_list,
2846 channel = silc_idlist_find_channel_by_id(server->global_list,
2849 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2850 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2855 /* Check whether this client is on the channel */
2856 if (!silc_server_client_on_channel(client, channel)) {
2857 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2858 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2862 /* Get entry to the channel user list */
2863 silc_list_start(channel->user_list);
2864 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2865 if (chl->client == client)
2868 /* Check that client has rights to change any requested channel modes */
2869 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2870 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2871 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2876 * Check the modes. Modes that requires nothing special operation are
2880 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2881 /* Channel uses private keys to protect traffic. Client(s) has set the
2882 key locally they want to use, server does not know that key. */
2883 /* Nothing interesting to do here now */
2885 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2886 /* The mode is removed and we need to generate and distribute
2887 new channel key. Clients are not using private channel keys
2888 anymore after this. */
2890 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2893 /* Re-generate channel key */
2894 silc_server_create_channel_key(server, channel, 0);
2896 /* Encode channel key payload to be distributed on the channel */
2898 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2899 strlen(channel->channel_key->
2901 channel->channel_key->cipher->name,
2902 channel->key_len / 8, channel->key);
2904 /* If we are normal server then we will send it to our router. If we
2905 are router we will send it to all local servers that has clients on
2907 if (server->server_type == SILC_SERVER) {
2908 if (!server->standalone)
2909 silc_server_packet_send(server,
2910 cmd->server->router->connection,
2911 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2917 /* Send to locally connected clients on the channel */
2918 silc_server_packet_send_local_channel(server, channel,
2919 SILC_PACKET_CHANNEL_KEY, 0,
2920 packet->data, packet->len, FALSE);
2921 silc_buffer_free(packet);
2925 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2926 /* User limit is set on channel */
2927 unsigned int user_limit;
2929 /* Get user limit */
2930 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2932 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2934 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2938 SILC_GET32_MSB(user_limit, tmp);
2939 channel->mode_data.user_limit = user_limit;
2942 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2943 /* User limit mode is unset. Remove user limit */
2944 channel->mode_data.user_limit = 0;
2947 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2948 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2949 /* Passphrase has been set to channel */
2951 /* Get the passphrase */
2952 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2955 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2959 /* Save the passphrase */
2960 channel->mode_data.passphrase = strdup(tmp);
2963 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2964 /* Passphrase mode is unset. remove the passphrase */
2965 if (channel->mode_data.passphrase) {
2966 silc_free(channel->mode_data.passphrase);
2967 channel->mode_data.passphrase = NULL;
2972 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2973 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2974 /* Ban list is specified for channel */
2977 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2980 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2984 /* XXX check that channel founder is not banned */
2986 /* Save the ban list */
2987 channel->mode_data.ban_list = strdup(tmp);
2990 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2991 /* Ban mode is unset. Remove the entire ban list */
2992 if (channel->mode_data.ban_list) {
2993 silc_free(channel->mode_data.ban_list);
2994 channel->mode_data.ban_list = NULL;
2999 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
3000 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
3001 /* Invite list is specified for channel */
3003 /* Get invite list */
3004 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
3006 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3007 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3011 /* Save the invite linst */
3012 channel->mode_data.invite_list = strdup(tmp);
3015 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
3016 /* Invite list mode is unset. Remove the entire invite list */
3017 if (channel->mode_data.invite_list) {
3018 silc_free(channel->mode_data.invite_list);
3019 channel->mode_data.invite_list = NULL;
3024 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3025 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3026 /* Cipher to use protect the traffic */
3027 unsigned int key_len;
3030 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
3032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3033 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3037 /* XXX Duplicated code, make own function for this!! */
3039 /* Delete old cipher and allocate the new one */
3040 silc_cipher_free(channel->channel_key);
3041 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
3042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3043 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3046 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
3048 /* Re-generate channel key */
3049 silc_server_create_channel_key(server, channel, key_len);
3051 /* Encode channel key payload to be distributed on the channel */
3053 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3054 strlen(channel->channel_key->
3056 channel->channel_key->cipher->name,
3057 channel->key_len / 8, channel->key);
3059 /* If we are normal server then we will send it to our router. If we
3060 are router we will send it to all local servers that has clients on
3062 if (server->server_type == SILC_SERVER) {
3063 if (!server->standalone)
3064 silc_server_packet_send(server,
3065 cmd->server->router->connection,
3066 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3072 /* Send to locally connected clients on the channel */
3073 silc_server_packet_send_local_channel(server, channel,
3074 SILC_PACKET_CHANNEL_KEY, 0,
3075 packet->data, packet->len, FALSE);
3076 silc_buffer_free(packet);
3079 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3080 /* Cipher mode is unset. Remove the cipher and revert back to
3083 if (channel->mode_data.cipher) {
3084 silc_free(channel->mode_data.cipher);
3085 channel->mode_data.cipher = NULL;
3086 channel->mode_data.key_len = 0;
3089 /* Generate new cipher and key for the channel */
3091 /* XXX Duplicated code, make own function for this!! */
3093 /* Delete old cipher and allocate default one */
3094 silc_cipher_free(channel->channel_key);
3095 if (!channel->cipher)
3096 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
3098 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
3099 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3100 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3105 /* Re-generate channel key */
3106 silc_server_create_channel_key(server, channel, 0);
3108 /* Encode channel key payload to be distributed on the channel */
3110 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3111 strlen(channel->channel_key->
3113 channel->channel_key->cipher->name,
3114 channel->key_len / 8, channel->key);
3116 /* If we are normal server then we will send it to our router. If we
3117 are router we will send it to all local servers that has clients on
3119 if (server->server_type == SILC_SERVER) {
3120 if (!server->standalone)
3121 silc_server_packet_send(server,
3122 cmd->server->router->connection,
3123 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3129 /* Send to locally connected clients on the channel */
3130 silc_server_packet_send_local_channel(server, channel,
3131 SILC_PACKET_CHANNEL_KEY, 0,
3132 packet->data, packet->len, FALSE);
3133 silc_buffer_free(packet);
3137 /* Finally, set the mode */
3138 channel->mode = mode_mask;
3140 /* Send CMODE_CHANGE notify */
3141 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3142 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3143 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
3144 cidp->data, cidp->len,
3147 /* Set CMODE notify type to network */
3148 if (!server->standalone)
3149 silc_server_send_notify_cmode(server, server->router->connection,
3150 server->server_type == SILC_ROUTER ?
3151 TRUE : FALSE, channel,
3152 mode_mask, client->id, SILC_ID_CLIENT_LEN);
3154 /* Send command reply to sender */
3155 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3156 SILC_STATUS_OK, ident, 1,
3158 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3159 packet->data, packet->len, FALSE);
3161 silc_buffer_free(packet);
3162 silc_free(channel_id);
3166 silc_server_command_free(cmd);
3169 /* Server side of CUMODE command. Changes client's mode on a channel. */
3171 SILC_SERVER_CMD_FUNC(cumode)
3173 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3174 SilcServer server = cmd->server;
3175 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3176 SilcChannelID *channel_id;
3177 SilcClientID *client_id;
3178 SilcChannelEntry channel;
3179 SilcClientEntry target_client;
3180 SilcChannelClientEntry chl;
3181 SilcBuffer packet, idp;
3182 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3183 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3185 unsigned short ident = silc_command_get_ident(cmd->payload);
3187 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3189 /* Get Channel ID */
3190 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3193 SILC_STATUS_ERR_NO_CHANNEL_ID);
3196 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3198 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3199 SILC_STATUS_ERR_NO_CHANNEL_ID);
3203 /* Get channel entry */
3204 channel = silc_idlist_find_channel_by_id(server->local_list,
3207 channel = silc_idlist_find_channel_by_id(server->global_list,
3210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3211 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3216 /* Check whether sender is on the channel */
3217 if (!silc_server_client_on_channel(client, channel)) {
3218 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3219 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3223 /* Check that client has rights to change other's rights */
3224 silc_list_start(channel->user_list);
3225 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3226 if (chl->client == client) {
3227 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3228 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3229 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3230 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3234 sender_mask = chl->mode;
3239 /* Get the target client's channel mode mask */
3240 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3243 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3246 SILC_GET32_MSB(target_mask, tmp_mask);
3248 /* Get target Client ID */
3249 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3251 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3252 SILC_STATUS_ERR_NO_CLIENT_ID);
3255 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3257 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3258 SILC_STATUS_ERR_NO_CLIENT_ID);
3262 /* Get target client's entry */
3263 target_client = silc_idlist_find_client_by_id(server->local_list,
3265 if (!target_client) {
3266 target_client = silc_idlist_find_client_by_id(server->global_list,
3270 /* Check whether target client is on the channel */
3271 if (!silc_server_client_on_channel(target_client, channel)) {
3272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3273 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3277 /* Get entry to the channel user list */
3278 silc_list_start(channel->user_list);
3279 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3280 if (chl->client == target_client)
3287 /* If the target client is founder, no one else can change their mode
3289 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3291 SILC_STATUS_ERR_NOT_YOU);
3295 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3296 /* Cannot promote anyone to channel founder */
3297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3298 SILC_STATUS_ERR_NOT_YOU);
3301 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3302 if (target_client == client) {
3303 /* Remove channel founder rights from itself */
3304 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3308 SILC_STATUS_ERR_NOT_YOU);
3314 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3315 /* Promote to operator */
3316 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3317 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3321 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3322 /* Demote to normal user */
3323 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3328 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3330 /* Send notify to channel, notify only if mode was actually changed. */
3332 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3333 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3334 idp->data, idp->len,
3338 /* Set CUMODE notify type to network */
3339 if (!server->standalone)
3340 silc_server_send_notify_cumode(server, server->router->connection,
3341 server->server_type == SILC_ROUTER ?
3342 TRUE : FALSE, channel,
3343 target_mask, client->id,
3346 SILC_ID_CLIENT_LEN);
3349 /* Send command reply to sender */
3350 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3351 SILC_STATUS_OK, ident, 2,
3353 3, tmp_id, tmp_len);
3354 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3355 packet->data, packet->len, FALSE);
3357 silc_buffer_free(packet);
3358 silc_free(channel_id);
3359 silc_free(client_id);
3360 silc_buffer_free(idp);
3363 silc_server_command_free(cmd);
3366 /* Server side of KICK command. Kicks client out of channel. */
3368 SILC_SERVER_CMD_FUNC(kick)
3370 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3371 SilcServer server = cmd->server;
3372 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3373 SilcClientEntry target_client;
3374 SilcChannelID *channel_id;
3375 SilcClientID *client_id;
3376 SilcChannelEntry channel;
3377 SilcChannelClientEntry chl;
3379 unsigned int tmp_len;
3380 unsigned char *tmp, *comment;
3382 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3384 /* Get Channel ID */
3385 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3388 SILC_STATUS_ERR_NO_CHANNEL_ID);
3391 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3393 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3394 SILC_STATUS_ERR_NO_CHANNEL_ID);
3398 /* Get channel entry */
3399 channel = silc_idlist_find_channel_by_id(server->local_list,
3402 channel = silc_idlist_find_channel_by_id(server->local_list,
3405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3406 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3411 /* Check whether sender is on the channel */
3412 if (!silc_server_client_on_channel(client, channel)) {
3413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3414 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3418 /* Check that the kicker is channel operator or channel founder */
3419 silc_list_start(channel->user_list);
3420 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3421 if (chl->client == client) {
3422 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3424 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3431 /* Get target Client ID */
3432 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3435 SILC_STATUS_ERR_NO_CLIENT_ID);
3438 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3441 SILC_STATUS_ERR_NO_CLIENT_ID);
3445 /* Get target client's entry */
3446 target_client = silc_idlist_find_client_by_id(server->local_list,
3448 if (!target_client) {
3449 target_client = silc_idlist_find_client_by_id(server->global_list,
3453 /* Check that the target client is not channel founder. Channel founder
3454 cannot be kicked from the channel. */
3455 silc_list_start(channel->user_list);
3456 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3457 if (chl->client == target_client) {
3458 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3459 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3460 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3467 /* Check whether target client is on the channel */
3468 if (!silc_server_client_on_channel(target_client, channel)) {
3469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3470 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3476 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3480 /* Send command reply to sender */
3481 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3484 /* Send KICKED notify to local clients on the channel */
3485 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3486 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3487 SILC_NOTIFY_TYPE_KICKED,
3489 idp->data, idp->len,
3490 comment, comment ? strlen(comment) : 0);
3491 silc_buffer_free(idp);
3493 /* Remove the client from the channel. If the channel does not exist
3494 after removing the client then the client kicked itself off the channel
3495 and we don't have to send anything after that. */
3496 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3497 target_client, FALSE))
3500 /* Send KICKED notify to primary route */
3501 if (!server->standalone)
3502 silc_server_send_notify_kicked(server, server->router->connection,
3503 server->server_type == SILC_ROUTER ?
3504 TRUE : FALSE, channel,
3505 target_client->id, SILC_ID_CLIENT_LEN,
3508 /* Re-generate channel key */
3509 silc_server_create_channel_key(server, channel, 0);
3511 /* Send the channel key to the channel. The key of course is not sent
3512 to the client who was kicked off the channel. */
3513 silc_server_send_channel_key(server, target_client->connection, channel,
3514 server->server_type == SILC_ROUTER ?
3515 FALSE : !server->standalone);
3518 silc_server_command_free(cmd);
3521 /* Server side of OPER command. Client uses this comand to obtain server
3522 operator privileges to this server/router. */
3524 SILC_SERVER_CMD_FUNC(oper)
3526 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3527 SilcServer server = cmd->server;
3528 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3529 unsigned char *username, *auth;
3530 unsigned int tmp_len;
3531 SilcServerConfigSectionAdminConnection *admin;
3532 SilcIDListData idata = (SilcIDListData)client;
3534 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
3536 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3539 /* Get the username */
3540 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3543 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3547 /* Get the admin configuration */
3548 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3549 username, client->nickname);
3551 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3552 username, client->nickname);
3554 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3555 SILC_STATUS_ERR_AUTH_FAILED);
3560 /* Get the authentication payload */
3561 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3563 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3564 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3568 /* Verify the authentication data */
3569 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3570 admin->auth_data, admin->auth_data_len,
3571 idata->hash, client->id, SILC_ID_CLIENT)) {
3572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3573 SILC_STATUS_ERR_AUTH_FAILED);
3577 /* Client is now server operator */
3578 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3580 /* Send UMODE change to primary router */
3581 if (!server->standalone)
3582 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3583 client->id, SILC_ID_CLIENT_LEN,
3586 /* Send reply to the sender */
3587 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3591 silc_server_command_free(cmd);
3594 /* Server side of SILCOPER command. Client uses this comand to obtain router
3595 operator privileges to this router. */
3597 SILC_SERVER_CMD_FUNC(silcoper)
3599 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3600 SilcServer server = cmd->server;
3601 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3602 unsigned char *username, *auth;
3603 unsigned int tmp_len;
3604 SilcServerConfigSectionAdminConnection *admin;
3605 SilcIDListData idata = (SilcIDListData)client;
3607 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
3609 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3612 /* Get the username */
3613 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3616 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3620 /* Get the admin configuration */
3621 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3622 username, client->nickname);
3624 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3625 username, client->nickname);
3627 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3628 SILC_STATUS_ERR_AUTH_FAILED);
3633 /* Get the authentication payload */
3634 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3637 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3641 /* Verify the authentication data */
3642 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3643 admin->auth_data, admin->auth_data_len,
3644 idata->hash, client->id, SILC_ID_CLIENT)) {
3645 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3646 SILC_STATUS_ERR_AUTH_FAILED);
3650 /* Client is now router operator */
3651 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
3653 /* Send UMODE change to primary router */
3654 if (!server->standalone)
3655 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3656 client->id, SILC_ID_CLIENT_LEN,
3659 /* Send reply to the sender */
3660 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3664 silc_server_command_free(cmd);
3667 /* Server side command of CONNECT. Connects us to the specified remote
3668 server or router. */
3670 SILC_SERVER_CMD_FUNC(connect)
3672 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3673 SilcServer server = cmd->server;
3674 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3675 unsigned char *tmp, *host;
3676 unsigned int tmp_len;
3677 unsigned int port = SILC_PORT;
3679 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
3681 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3684 /* Check whether client has the permissions. */
3685 if (client->mode == SILC_UMODE_NONE) {
3686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3687 SILC_STATUS_ERR_NO_SERVER_PRIV);
3691 if (server->server_type == SILC_ROUTER &&
3692 client->mode & SILC_UMODE_SERVER_OPERATOR) {
3693 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3694 SILC_STATUS_ERR_NO_ROUTER_PRIV);
3698 /* Get the remote server */
3699 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3701 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3702 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3707 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3709 SILC_GET32_MSB(port, tmp);
3711 /* Create the connection. It is done with timeout and is async. */
3712 silc_server_create_connection(server, host, port);
3714 /* Send reply to the sender */
3715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3719 silc_server_command_free(cmd);
3722 SILC_SERVER_CMD_FUNC(restart)
3726 /* Server side command of CLOSE. Closes connection to a specified server. */
3728 SILC_SERVER_CMD_FUNC(close)
3730 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3731 SilcServer server = cmd->server;
3732 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3733 SilcServerEntry server_entry;
3734 SilcSocketConnection sock;
3736 unsigned int tmp_len;
3737 unsigned char *name;
3738 unsigned int port = SILC_PORT;
3740 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3742 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3745 /* Check whether client has the permissions. */
3746 if (client->mode == SILC_UMODE_NONE) {
3747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3748 SILC_STATUS_ERR_NO_SERVER_PRIV);
3752 /* Get the remote server */
3753 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3755 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3756 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3761 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3763 SILC_GET32_MSB(port, tmp);
3765 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3767 if (!server_entry) {
3768 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3769 SILC_STATUS_ERR_NO_SERVER_ID);
3773 /* Send reply to the sender */
3774 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3777 /* Close the connection to the server */
3778 sock = (SilcSocketConnection)server_entry->connection;
3779 silc_server_free_sock_user_data(server, sock);
3780 silc_server_close_connection(server, sock);
3783 silc_server_command_free(cmd);
3786 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3787 active connections. */
3789 SILC_SERVER_CMD_FUNC(shutdown)
3791 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3792 SilcServer server = cmd->server;
3793 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3795 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3797 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3800 /* Check whether client has the permission. */
3801 if (client->mode == SILC_UMODE_NONE) {
3802 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3803 SILC_STATUS_ERR_NO_SERVER_PRIV);
3807 /* Send reply to the sender */
3808 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3811 /* Then, gracefully, or not, bring the server down. */
3812 silc_server_stop(server);
3816 silc_server_command_free(cmd);
3819 /* Server side command of LEAVE. Removes client from a channel. */
3821 SILC_SERVER_CMD_FUNC(leave)
3823 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3824 SilcServer server = cmd->server;
3825 SilcSocketConnection sock = cmd->sock;
3826 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3828 SilcChannelEntry channel;
3830 unsigned int i, len;
3833 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3835 /* Get Channel ID */
3836 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3838 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3839 SILC_STATUS_ERR_NO_CHANNEL_ID);
3842 id = silc_id_payload_parse_id(tmp, len);
3844 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3845 SILC_STATUS_ERR_NO_CHANNEL_ID);
3849 /* Get channel entry */
3850 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3852 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3854 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3855 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3860 /* Check whether this client is on the channel */
3861 if (!silc_server_client_on_channel(id_entry, channel)) {
3862 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3863 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3867 /* Notify routers that they should remove this client from their list
3868 of clients on the channel. Send LEAVE notify type. */
3869 if (!server->standalone)
3870 silc_server_send_notify_leave(server, server->router->connection,
3871 server->server_type == SILC_ROUTER ?
3872 TRUE : FALSE, channel, id_entry->id,
3873 SILC_ID_CLIENT_LEN);
3875 /* Remove client from channel */
3876 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3878 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3881 /* If the channel does not exist anymore we won't send anything */
3885 /* Re-generate channel key */
3886 silc_server_create_channel_key(server, channel, 0);
3888 /* Encode channel key payload to be distributed on the channel */
3890 silc_channel_key_payload_encode(len, tmp,
3891 strlen(channel->channel_key->cipher->name),
3892 channel->channel_key->cipher->name,
3893 channel->key_len / 8, channel->key);
3895 /* If we are normal server then we will send it to our router. If we
3896 are router we will send it to all local servers that has clients on
3898 if (server->server_type == SILC_SERVER) {
3899 if (!server->standalone)
3900 silc_server_packet_send(server,
3901 cmd->server->router->connection,
3902 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3903 packet->len, FALSE);
3908 /* Send to locally connected clients on the channel */
3909 silc_server_packet_send_local_channel(server, channel,
3910 SILC_PACKET_CHANNEL_KEY, 0,
3911 packet->data, packet->len, FALSE);
3913 silc_buffer_free(packet);
3917 silc_server_command_free(cmd);
3920 /* Server side of command USERS. Resolves clients and their USERS currently
3921 joined on the requested channel. The list of Client ID's and their modes
3922 on the channel is sent back. */
3924 SILC_SERVER_CMD_FUNC(users)
3926 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3927 SilcServer server = cmd->server;
3928 SilcChannelEntry channel;
3931 unsigned char *channel_id;
3932 unsigned int channel_id_len;
3933 SilcBuffer client_id_list;
3934 SilcBuffer client_mode_list;
3935 unsigned char lc[4];
3936 unsigned int list_count = 0;
3937 unsigned short ident = silc_command_get_ident(cmd->payload);
3939 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3941 /* Get Channel ID */
3942 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3945 SILC_STATUS_ERR_NO_CHANNEL_ID);
3948 id = silc_id_payload_parse_id(channel_id, channel_id_len);
3950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3951 SILC_STATUS_ERR_NO_CHANNEL_ID);
3955 /* If we are server and we don't know about this channel we will send
3956 the command to our router. If we know about the channel then we also
3957 have the list of users already. */
3958 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3960 if (server->server_type == SILC_SERVER && !server->standalone &&
3964 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3965 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3967 /* Send USERS command */
3968 silc_server_packet_send(server, server->router->connection,
3969 SILC_PACKET_COMMAND, cmd->packet->flags,
3970 tmpbuf->data, tmpbuf->len, TRUE);
3972 /* Reprocess this packet after received reply */
3973 silc_server_command_pending(server, SILC_COMMAND_USERS,
3974 silc_command_get_ident(cmd->payload),
3975 silc_server_command_destructor,
3976 silc_server_command_users,
3977 silc_server_command_dup(cmd));
3978 cmd->pending = TRUE;
3979 silc_command_set_ident(cmd->payload, ident);
3981 silc_buffer_free(tmpbuf);
3986 /* We are router and we will check the global list as well. */
3987 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3989 /* Channel really does not exist */
3990 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3991 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3996 /* Get the users list */
3997 silc_server_get_users_on_channel(server, channel, &client_id_list,
3998 &client_mode_list, &list_count);
4001 SILC_PUT32_MSB(list_count, lc);
4004 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4005 SILC_STATUS_OK, ident, 4,
4006 2, channel_id, channel_id_len,
4008 4, client_id_list->data,
4009 client_id_list->len,
4010 5, client_mode_list->data,
4011 client_mode_list->len);
4012 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4013 packet->data, packet->len, FALSE);
4015 silc_buffer_free(packet);
4016 silc_buffer_free(client_id_list);
4017 silc_buffer_free(client_mode_list);
4021 silc_server_command_free(cmd);