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) {
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;
533 SilcClientEntry entry;
534 SilcCommandStatus status;
535 unsigned short ident = silc_command_get_ident(cmd->payload);
537 status = SILC_STATUS_OK;
538 if (clients_count > 1)
539 status = SILC_STATUS_LIST_START;
541 for (i = 0; i < clients_count; i++) {
544 if (entry->connection && entry->data.registered == FALSE) {
545 if (clients_count == 1)
546 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
547 SILC_STATUS_ERR_NO_SUCH_NICK,
549 strlen(entry->nickname));
553 if (count && i - 1 == count)
556 if (clients_count > 2)
557 status = SILC_STATUS_LIST_ITEM;
559 if (clients_count > 1 && i == clients_count - 1)
560 status = SILC_STATUS_LIST_END;
562 /* Sanity check, however these should never fail. However, as
563 this sanity check has been added here they have failed. */
564 if (!entry->nickname || !entry->username)
567 /* Send WHOIS reply */
568 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
569 tmp = silc_argument_get_first_arg(cmd->args, NULL);
572 char nh[256], uh[256];
573 unsigned char idle[4];
574 SilcSocketConnection hsock;
576 memset(uh, 0, sizeof(uh));
577 memset(nh, 0, sizeof(nh));
579 strncat(nh, entry->nickname, strlen(entry->nickname));
580 if (!strchr(entry->nickname, '@')) {
582 len = entry->router ? strlen(entry->router->server_name) :
583 strlen(server->server_name);
584 strncat(nh, entry->router ? entry->router->server_name :
585 server->server_name, len);
588 strncat(uh, entry->username, strlen(entry->username));
589 if (!strchr(entry->username, '@')) {
591 hsock = (SilcSocketConnection)entry->connection;
592 len = strlen(hsock->hostname);
593 strncat(uh, hsock->hostname, len);
596 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
599 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
601 2, idp->data, idp->len,
605 strlen(entry->userinfo),
609 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
610 0, packet->data, packet->len, FALSE);
612 silc_buffer_free(packet);
613 silc_buffer_free(idp);
618 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
620 SilcServer server = cmd->server;
621 char *nick = NULL, *server_name = NULL;
622 int count = 0, clients_count = 0;
623 SilcClientEntry *clients = NULL, entry;
624 SilcClientID **client_id = NULL;
625 unsigned int client_id_count = 0;
628 /* Protocol dictates that we must always send the received WHOIS request
629 to our router if we are normal server, so let's do it now unless we
630 are standalone. We will not send any replies to the client until we
631 have received reply from the router. */
632 if (server->server_type == SILC_SERVER &&
633 !cmd->pending && !server->standalone) {
635 unsigned short old_ident;
637 old_ident = silc_command_get_ident(cmd->payload);
638 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
639 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
641 /* Send WHOIS command to our router */
642 silc_server_packet_send(server, (SilcSocketConnection)
643 server->router->connection,
644 SILC_PACKET_COMMAND, cmd->packet->flags,
645 tmpbuf->data, tmpbuf->len, TRUE);
647 /* Reprocess this packet after received reply from router */
648 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
649 silc_command_get_ident(cmd->payload),
650 silc_server_command_destructor,
651 silc_server_command_whois,
652 silc_server_command_dup(cmd));
655 silc_command_set_ident(cmd->payload, old_ident);
657 silc_buffer_free(tmpbuf);
662 /* We are ready to process the command request. Let's search for the
663 requested client and send reply to the requesting client. */
665 /* Parse the whois request */
666 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
667 &nick, &server_name, &count,
671 /* Get all clients matching that ID or nickname from local list */
672 if (client_id_count) {
673 /* Check all Client ID's received in the command packet */
674 for (i = 0; i < client_id_count; i++) {
675 entry = silc_idlist_find_client_by_id(server->local_list,
678 clients = silc_realloc(clients, sizeof(*clients) *
679 (clients_count + 1));
680 clients[clients_count++] = entry;
684 clients = silc_idlist_get_clients_by_nickname(server->local_list,
688 clients = silc_idlist_get_clients_by_hash(server->local_list,
689 nick, server->md5hash,
693 /* Check global list as well */
695 if (client_id_count) {
696 /* Check all Client ID's received in the command packet */
697 for (i = 0; i < client_id_count; i++) {
698 entry = silc_idlist_find_client_by_id(server->global_list,
701 clients = silc_realloc(clients, sizeof(*clients) *
702 (clients_count + 1));
703 clients[clients_count++] = entry;
707 clients = silc_idlist_get_clients_by_nickname(server->global_list,
711 clients = silc_idlist_get_clients_by_hash(server->global_list,
712 nick, server->md5hash,
718 /* Such client(s) really does not exist in the SILC network. */
719 if (!client_id_count) {
720 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
721 SILC_STATUS_ERR_NO_SUCH_NICK,
722 3, nick, strlen(nick));
724 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
725 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
726 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
727 2, idp->data, idp->len);
728 silc_buffer_free(idp);
733 /* Router always finds the client entry if it exists in the SILC network.
734 However, it might be incomplete entry and does not include all the
735 mandatory fields that WHOIS command reply requires. Check for these and
736 make query from the server who owns the client if some fields are
738 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
743 /* Send the command reply to the client */
744 silc_server_command_whois_send_reply(cmd, clients, clients_count);
747 if (client_id_count) {
748 for (i = 0; i < client_id_count; i++)
749 silc_free(client_id[i]);
750 silc_free(client_id);
757 silc_free(server_name);
763 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
765 SilcServer server = cmd->server;
766 char *nick = NULL, *server_name = NULL;
767 int count = 0, clients_count = 0;
768 SilcClientEntry *clients = NULL, entry;
769 SilcClientID **client_id = NULL;
770 unsigned int client_id_count = 0;
773 /* Parse the whois request */
774 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
775 &nick, &server_name, &count,
779 /* Process the command request. Let's search for the requested client and
780 send reply to the requesting server. */
782 if (client_id_count) {
783 /* Check all Client ID's received in the command packet */
784 for (i = 0; i < client_id_count; i++) {
785 entry = silc_idlist_find_client_by_id(server->local_list,
788 clients = silc_realloc(clients, sizeof(*clients) *
789 (clients_count + 1));
790 clients[clients_count++] = entry;
794 clients = silc_idlist_get_clients_by_nickname(server->local_list,
798 clients = silc_idlist_get_clients_by_hash(server->local_list,
799 nick, server->md5hash,
803 /* If we are router we will check our global list as well. */
804 if (!clients && server->server_type == SILC_ROUTER) {
805 if (client_id_count) {
806 /* Check all Client ID's received in the command packet */
807 for (i = 0; i < client_id_count; i++) {
808 entry = silc_idlist_find_client_by_id(server->global_list,
811 clients = silc_realloc(clients, sizeof(*clients) *
812 (clients_count + 1));
813 clients[clients_count++] = entry;
817 clients = silc_idlist_get_clients_by_nickname(server->global_list,
821 clients = silc_idlist_get_clients_by_hash(server->global_list,
822 nick, server->md5hash,
828 /* Such a client really does not exist in the SILC network. */
829 if (!client_id_count) {
830 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
831 SILC_STATUS_ERR_NO_SUCH_NICK,
832 3, nick, strlen(nick));
834 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
835 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
836 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
837 2, idp->data, idp->len);
838 silc_buffer_free(idp);
843 /* Router always finds the client entry if it exists in the SILC network.
844 However, it might be incomplete entry and does not include all the
845 mandatory fields that WHOIS command reply requires. Check for these and
846 make query from the server who owns the client if some fields are
848 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
853 /* Send the command reply to the client */
854 silc_server_command_whois_send_reply(cmd, clients, clients_count);
857 if (client_id_count) {
858 for (i = 0; i < client_id_count; i++)
859 silc_free(client_id[i]);
860 silc_free(client_id);
867 silc_free(server_name);
872 /* Server side of command WHOIS. Processes user's query and sends found
873 results as command replies back to the client. */
875 SILC_SERVER_CMD_FUNC(whois)
877 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
880 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
882 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
883 ret = silc_server_command_whois_from_client(cmd);
884 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
885 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
886 ret = silc_server_command_whois_from_server(cmd);
889 silc_server_command_free(cmd);
892 /******************************************************************************
896 ******************************************************************************/
899 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
907 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
909 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
910 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
914 /* Get the nickname@server string and parse it. */
915 if (strchr(tmp, '@')) {
916 len = strcspn(tmp, "@");
917 *nickname = silc_calloc(len + 1, sizeof(char));
918 memcpy(*nickname, tmp, len);
919 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
920 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
922 *nickname = strdup(tmp);
924 /* Get the max count of reply messages allowed */
925 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
935 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
936 SilcClientEntry *clients,
937 unsigned int clients_count)
939 SilcServer server = cmd->server;
941 int i, count = 0, len;
942 SilcBuffer packet, idp;
943 SilcClientEntry entry = NULL;
944 SilcCommandStatus status;
945 unsigned short ident = silc_command_get_ident(cmd->payload);
948 status = SILC_STATUS_OK;
949 if (clients_count > 1)
950 status = SILC_STATUS_LIST_START;
952 for (i = 0; i < clients_count; i++) {
955 /* We will take only clients that are not valid anymore. They are the
956 ones that are not registered anymore but still have a ID. They
957 have disconnected us, and thus valid for WHOWAS. */
958 if (entry->data.registered == TRUE)
960 if (entry->id == NULL)
963 if (count && i - 1 == count)
968 if (clients_count > 2)
969 status = SILC_STATUS_LIST_ITEM;
971 if (clients_count > 1 && i == clients_count - 1)
972 status = SILC_STATUS_LIST_END;
974 /* Sanity check, however these should never fail. However, as
975 this sanity check has been added here they have failed. */
976 if (!entry->nickname || !entry->username)
979 /* Send WHOWAS reply */
980 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
981 tmp = silc_argument_get_first_arg(cmd->args, NULL);
984 char nh[256], uh[256];
986 memset(uh, 0, sizeof(uh));
987 memset(nh, 0, sizeof(nh));
989 strncat(nh, entry->nickname, strlen(entry->nickname));
990 if (!strchr(entry->nickname, '@')) {
992 len = entry->router ? strlen(entry->router->server_name) :
993 strlen(server->server_name);
994 strncat(nh, entry->router ? entry->router->server_name :
995 server->server_name, len);
998 strncat(uh, entry->username, strlen(entry->username));
999 if (!strchr(entry->username, '@')) {
1000 strncat(uh, "@", 1);
1001 strcat(uh, "*private*");
1005 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1007 2, idp->data, idp->len,
1011 strlen(entry->userinfo));
1014 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1015 0, packet->data, packet->len, FALSE);
1017 silc_buffer_free(packet);
1018 silc_buffer_free(idp);
1021 if (found == FALSE && entry)
1022 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1023 SILC_STATUS_ERR_NO_SUCH_NICK,
1025 strlen(entry->nickname));
1029 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1031 SilcServer server = cmd->server;
1032 char *nick = NULL, *server_name = NULL;
1033 int count = 0, clients_count = 0;
1034 SilcClientEntry *clients = NULL;
1037 /* Protocol dictates that we must always send the received WHOWAS request
1038 to our router if we are normal server, so let's do it now unless we
1039 are standalone. We will not send any replies to the client until we
1040 have received reply from the router. */
1041 if (server->server_type == SILC_SERVER &&
1042 !cmd->pending && !server->standalone) {
1044 unsigned short old_ident;
1046 old_ident = silc_command_get_ident(cmd->payload);
1047 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1048 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1050 /* Send WHOWAS command to our router */
1051 silc_server_packet_send(server, (SilcSocketConnection)
1052 server->router->connection,
1053 SILC_PACKET_COMMAND, cmd->packet->flags,
1054 tmpbuf->data, tmpbuf->len, TRUE);
1056 /* Reprocess this packet after received reply from router */
1057 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1058 silc_command_get_ident(cmd->payload),
1059 silc_server_command_destructor,
1060 silc_server_command_whois,
1061 silc_server_command_dup(cmd));
1062 cmd->pending = TRUE;
1064 silc_command_set_ident(cmd->payload, old_ident);
1066 silc_buffer_free(tmpbuf);
1071 /* We are ready to process the command request. Let's search for the
1072 requested client and send reply to the requesting client. */
1074 /* Parse the whowas request */
1075 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1078 /* Get all clients matching that nickname from local list */
1079 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1083 clients = silc_idlist_get_clients_by_hash(server->local_list,
1084 nick, server->md5hash,
1087 /* Check global list as well */
1089 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1093 clients = silc_idlist_get_clients_by_hash(server->global_list,
1094 nick, server->md5hash,
1099 /* Such client(s) really does not exist in the SILC network. */
1100 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1101 SILC_STATUS_ERR_NO_SUCH_NICK,
1102 3, nick, strlen(nick));
1106 /* Send the command reply to the client */
1107 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1115 silc_free(server_name);
1121 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1123 SilcServer server = cmd->server;
1124 char *nick = NULL, *server_name = NULL;
1125 int count = 0, clients_count = 0;
1126 SilcClientEntry *clients = NULL;
1129 /* Parse the whowas request */
1130 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1133 /* Process the command request. Let's search for the requested client and
1134 send reply to the requesting server. */
1136 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1140 clients = silc_idlist_get_clients_by_hash(server->local_list,
1141 nick, server->md5hash,
1144 /* If we are router we will check our global list as well. */
1145 if (!clients && server->server_type == SILC_ROUTER) {
1146 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1150 clients = silc_idlist_get_clients_by_hash(server->global_list,
1151 nick, server->md5hash,
1156 /* Such a client really does not exist in the SILC network. */
1157 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1158 SILC_STATUS_ERR_NO_SUCH_NICK,
1159 3, nick, strlen(nick));
1163 /* Send the command reply to the client */
1164 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1172 silc_free(server_name);
1177 /* Server side of command WHOWAS. */
1179 SILC_SERVER_CMD_FUNC(whowas)
1181 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1184 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1186 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1187 ret = silc_server_command_whowas_from_client(cmd);
1188 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1189 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1190 ret = silc_server_command_whowas_from_server(cmd);
1193 silc_server_command_free(cmd);
1196 /******************************************************************************
1200 ******************************************************************************/
1202 /* Checks that all mandatory fields are present. If not then send WHOIS
1203 request to the server who owns the client. We use WHOIS because we want
1204 to get as much information as possible at once. */
1207 silc_server_command_identify_check(SilcServerCommandContext cmd,
1208 SilcClientEntry *clients,
1209 unsigned int clients_count)
1211 SilcServer server = cmd->server;
1213 SilcClientEntry entry;
1215 for (i = 0; i < clients_count; i++) {
1218 if (!entry->nickname) {
1220 unsigned short old_ident;
1225 old_ident = silc_command_get_ident(cmd->payload);
1226 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1227 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1228 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1230 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1231 now anyway so make it a good one. */
1232 silc_server_packet_send(server, entry->router->connection,
1233 SILC_PACKET_COMMAND, cmd->packet->flags,
1234 tmpbuf->data, tmpbuf->len, TRUE);
1236 /* Reprocess this packet after received reply */
1237 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1238 silc_command_get_ident(cmd->payload),
1239 silc_server_command_destructor,
1240 silc_server_command_identify,
1241 silc_server_command_dup(cmd));
1243 cmd->pending = TRUE;
1245 /* Put old data back to the Command Payload we just changed */
1246 silc_command_set_ident(cmd->payload, old_ident);
1247 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1249 silc_buffer_free(tmpbuf);
1258 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1259 SilcClientEntry *clients,
1260 unsigned int clients_count)
1262 SilcServer server = cmd->server;
1264 int i, count = 0, len;
1265 SilcBuffer packet, idp;
1266 SilcClientEntry entry;
1267 SilcCommandStatus status;
1268 unsigned short ident = silc_command_get_ident(cmd->payload);
1270 status = SILC_STATUS_OK;
1271 if (clients_count > 1)
1272 status = SILC_STATUS_LIST_START;
1274 for (i = 0; i < clients_count; i++) {
1277 if (entry->connection && entry->data.registered == FALSE) {
1278 if (clients_count == 1)
1279 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1280 SILC_STATUS_ERR_NO_SUCH_NICK,
1282 strlen(entry->nickname));
1286 if (count && i - 1 == count)
1289 if (clients_count > 2)
1290 status = SILC_STATUS_LIST_ITEM;
1292 if (clients_count > 1 && i == clients_count - 1)
1293 status = SILC_STATUS_LIST_END;
1295 /* Send IDENTIFY reply */
1296 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1297 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1301 char nh[256], uh[256];
1302 SilcSocketConnection hsock;
1304 memset(uh, 0, sizeof(uh));
1305 memset(nh, 0, sizeof(nh));
1307 strncat(nh, entry->nickname, strlen(entry->nickname));
1308 if (!strchr(entry->nickname, '@')) {
1309 strncat(nh, "@", 1);
1310 len = entry->router ? strlen(entry->router->server_name) :
1311 strlen(server->server_name);
1312 strncat(nh, entry->router ? entry->router->server_name :
1313 server->server_name, len);
1316 if (!entry->username) {
1317 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1319 2, idp->data, idp->len,
1322 strncat(uh, entry->username, strlen(entry->username));
1323 if (!strchr(entry->username, '@')) {
1324 strncat(uh, "@", 1);
1325 hsock = (SilcSocketConnection)entry->connection;
1326 len = strlen(hsock->hostname);
1327 strncat(uh, hsock->hostname, len);
1330 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1332 2, idp->data, idp->len,
1337 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1338 0, packet->data, packet->len, FALSE);
1340 silc_buffer_free(packet);
1341 silc_buffer_free(idp);
1347 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1349 SilcServer server = cmd->server;
1350 char *nick = NULL, *server_name = NULL;
1351 int count = 0, clients_count = 0;
1352 SilcClientEntry *clients = NULL, entry;
1353 SilcClientID **client_id = NULL;
1354 unsigned int client_id_count = 0;
1357 /* Protocol dictates that we must always send the received IDENTIFY request
1358 to our router if we are normal server, so let's do it now unless we
1359 are standalone. We will not send any replies to the client until we
1360 have received reply from the router. */
1361 if (server->server_type == SILC_SERVER &&
1362 !cmd->pending && !server->standalone) {
1364 unsigned short old_ident;
1366 old_ident = silc_command_get_ident(cmd->payload);
1367 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1368 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1370 /* Send IDENTIFY command to our router */
1371 silc_server_packet_send(server, (SilcSocketConnection)
1372 server->router->connection,
1373 SILC_PACKET_COMMAND, cmd->packet->flags,
1374 tmpbuf->data, tmpbuf->len, TRUE);
1376 /* Reprocess this packet after received reply from router */
1377 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1378 silc_command_get_ident(cmd->payload),
1379 silc_server_command_destructor,
1380 silc_server_command_identify,
1381 silc_server_command_dup(cmd));
1382 cmd->pending = TRUE;
1384 silc_command_set_ident(cmd->payload, old_ident);
1386 silc_buffer_free(tmpbuf);
1391 /* We are ready to process the command request. Let's search for the
1392 requested client and send reply to the requesting client. */
1394 /* Parse the IDENTIFY request */
1395 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1396 &nick, &server_name, &count,
1397 SILC_COMMAND_IDENTIFY))
1400 /* Get all clients matching that ID or nickname from local list */
1401 if (client_id_count) {
1402 /* Check all Client ID's received in the command packet */
1403 for (i = 0; i < client_id_count; i++) {
1404 entry = silc_idlist_find_client_by_id(server->local_list,
1405 client_id[i], NULL);
1407 clients = silc_realloc(clients, sizeof(*clients) *
1408 (clients_count + 1));
1409 clients[clients_count++] = entry;
1413 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1417 clients = silc_idlist_get_clients_by_hash(server->local_list,
1418 nick, server->md5hash,
1422 /* Check global list as well */
1424 if (client_id_count) {
1425 /* Check all Client ID's received in the command packet */
1426 for (i = 0; i < client_id_count; i++) {
1427 entry = silc_idlist_find_client_by_id(server->global_list,
1428 client_id[i], NULL);
1430 clients = silc_realloc(clients, sizeof(*clients) *
1431 (clients_count + 1));
1432 clients[clients_count++] = entry;
1436 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1440 clients = silc_idlist_get_clients_by_hash(server->global_list,
1441 nick, server->md5hash,
1447 /* Such a client really does not exist in the SILC network. */
1448 if (!client_id_count) {
1449 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1450 SILC_STATUS_ERR_NO_SUCH_NICK,
1451 3, nick, strlen(nick));
1453 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1454 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1455 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1456 2, idp->data, idp->len);
1457 silc_buffer_free(idp);
1462 /* Check that all mandatory fields are present and request those data
1463 from the server who owns the client if necessary. */
1464 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1469 /* Send the command reply to the client */
1470 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1473 if (client_id_count) {
1474 for (i = 0; i < client_id_count; i++)
1475 silc_free(client_id[i]);
1476 silc_free(client_id);
1483 silc_free(server_name);
1489 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1491 SilcServer server = cmd->server;
1492 char *nick = NULL, *server_name = NULL;
1493 int count = 0, clients_count = 0;
1494 SilcClientEntry *clients = NULL, entry;
1495 SilcClientID **client_id = NULL;
1496 unsigned int client_id_count = 0;
1499 /* Parse the IDENTIFY request */
1500 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1501 &nick, &server_name, &count,
1502 SILC_COMMAND_IDENTIFY))
1505 /* Process the command request. Let's search for the requested client and
1506 send reply to the requesting server. */
1508 if (client_id_count) {
1509 /* Check all Client ID's received in the command packet */
1510 for (i = 0; i < client_id_count; i++) {
1511 entry = silc_idlist_find_client_by_id(server->local_list,
1512 client_id[i], NULL);
1514 clients = silc_realloc(clients, sizeof(*clients) *
1515 (clients_count + 1));
1516 clients[clients_count++] = entry;
1520 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1524 clients = silc_idlist_get_clients_by_hash(server->local_list,
1525 nick, server->md5hash,
1529 /* If we are router we will check our global list as well. */
1530 if (!clients && server->server_type == SILC_ROUTER) {
1531 if (client_id_count) {
1532 /* Check all Client ID's received in the command packet */
1533 for (i = 0; i < client_id_count; i++) {
1534 entry = silc_idlist_find_client_by_id(server->global_list,
1535 client_id[i], NULL);
1537 clients = silc_realloc(clients, sizeof(*clients) *
1538 (clients_count + 1));
1539 clients[clients_count++] = entry;
1543 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1547 clients = silc_idlist_get_clients_by_hash(server->global_list,
1548 nick, server->md5hash,
1554 /* Such a client really does not exist in the SILC network. */
1555 if (!client_id_count) {
1556 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1557 SILC_STATUS_ERR_NO_SUCH_NICK,
1558 3, nick, strlen(nick));
1560 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1561 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1562 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1563 2, idp->data, idp->len);
1564 silc_buffer_free(idp);
1569 /* Check that all mandatory fields are present and request those data
1570 from the server who owns the client if necessary. */
1571 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1576 /* Send the command reply */
1577 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1580 if (client_id_count) {
1581 for (i = 0; i < client_id_count; i++)
1582 silc_free(client_id[i]);
1583 silc_free(client_id);
1590 silc_free(server_name);
1595 SILC_SERVER_CMD_FUNC(identify)
1597 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1600 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1602 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1603 ret = silc_server_command_identify_from_client(cmd);
1604 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1605 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1606 ret = silc_server_command_identify_from_server(cmd);
1609 silc_server_command_free(cmd);
1612 /* Checks string for bad characters and returns TRUE if they are found. */
1614 static int silc_server_command_bad_chars(char *nick)
1616 if (strchr(nick, '\\')) return TRUE;
1617 if (strchr(nick, '\"')) return TRUE;
1618 if (strchr(nick, '´')) return TRUE;
1619 if (strchr(nick, '`')) return TRUE;
1620 if (strchr(nick, '\'')) return TRUE;
1621 if (strchr(nick, '*')) return TRUE;
1622 if (strchr(nick, '/')) return TRUE;
1623 if (strchr(nick, '@')) return TRUE;
1628 /* Server side of command NICK. Sets nickname for user. Setting
1629 nickname causes generation of a new client ID for the client. The
1630 new client ID is sent to the client after changing the nickname. */
1632 SILC_SERVER_CMD_FUNC(nick)
1634 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1635 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1636 SilcServer server = cmd->server;
1637 SilcBuffer packet, nidp, oidp;
1638 SilcClientID *new_id;
1640 unsigned short ident = silc_command_get_ident(cmd->payload);
1642 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1645 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1647 /* Check nickname */
1648 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1649 if (silc_server_command_bad_chars(nick) == TRUE) {
1650 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1651 SILC_STATUS_ERR_BAD_NICKNAME);
1655 if (strlen(nick) > 128)
1658 /* Create new Client ID */
1659 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1660 cmd->server->md5hash, nick,
1663 /* Send notify about nickname change to our router. We send the new
1664 ID and ask to replace it with the old one. If we are router the
1665 packet is broadcasted. Send NICK_CHANGE notify. */
1666 if (!server->standalone)
1667 silc_server_send_notify_nick_change(server, server->router->connection,
1668 server->server_type == SILC_SERVER ?
1669 FALSE : TRUE, client->id,
1670 new_id, SILC_ID_CLIENT_LEN);
1672 /* Remove old cache entry */
1673 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1676 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1680 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1681 silc_free(client->id);
1684 /* Save the nickname as this client is our local client */
1685 if (client->nickname)
1686 silc_free(client->nickname);
1688 client->nickname = strdup(nick);
1689 client->id = new_id;
1691 /* Update client cache */
1692 silc_idcache_add(server->local_list->clients, client->nickname,
1693 SILC_ID_CLIENT, client->id, (void *)client, TRUE, FALSE);
1695 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1697 /* Send NICK_CHANGE notify to the client's channels */
1698 silc_server_send_notify_on_channels(server, NULL, client,
1699 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1700 oidp->data, oidp->len,
1701 nidp->data, nidp->len);
1703 /* Send the new Client ID as reply command back to client */
1704 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1705 SILC_STATUS_OK, ident, 1,
1706 2, nidp->data, nidp->len);
1707 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1708 0, packet->data, packet->len, FALSE);
1710 silc_buffer_free(packet);
1711 silc_buffer_free(nidp);
1712 silc_buffer_free(oidp);
1715 silc_server_command_free(cmd);
1718 SILC_SERVER_CMD_FUNC(list)
1722 /* Server side of TOPIC command. Sets topic for channel and/or returns
1723 current topic to client. */
1725 SILC_SERVER_CMD_FUNC(topic)
1727 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1728 SilcServer server = cmd->server;
1729 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1730 SilcChannelID *channel_id;
1731 SilcChannelEntry channel;
1732 SilcChannelClientEntry chl;
1733 SilcBuffer packet, idp;
1735 unsigned int argc, tmp_len;
1736 unsigned short ident = silc_command_get_ident(cmd->payload);
1738 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1740 argc = silc_argument_get_arg_num(cmd->args);
1742 /* Get Channel ID */
1743 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1745 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1746 SILC_STATUS_ERR_NO_CHANNEL_ID);
1749 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1751 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1752 SILC_STATUS_ERR_NO_CHANNEL_ID);
1756 /* Check whether the channel exists */
1757 channel = silc_idlist_find_channel_by_id(server->local_list,
1760 channel = silc_idlist_find_channel_by_id(server->global_list,
1763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1764 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1771 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1773 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1774 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1778 if (strlen(tmp) > 256) {
1779 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1780 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1784 /* See whether has rights to change topic */
1785 silc_list_start(channel->user_list);
1786 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1787 if (chl->client == client)
1790 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1791 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1792 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1793 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1798 /* Set the topic for channel */
1800 silc_free(channel->topic);
1801 channel->topic = strdup(tmp);
1803 /* Send TOPIC_SET notify type to the network */
1804 if (!server->standalone)
1805 silc_server_send_notify_topic_set(server, server->router->connection,
1806 server->server_type == SILC_ROUTER ?
1807 TRUE : FALSE, channel, client->id,
1808 SILC_ID_CLIENT_LEN, channel->topic);
1810 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1812 /* Send notify about topic change to all clients on the channel */
1813 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1814 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1815 idp->data, idp->len,
1816 channel->topic, strlen(channel->topic));
1817 silc_buffer_free(idp);
1820 /* Send the topic to client as reply packet */
1821 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1823 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1824 SILC_STATUS_OK, ident, 2,
1825 2, idp->data, idp->len,
1827 strlen(channel->topic));
1829 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1830 SILC_STATUS_OK, ident, 1,
1831 2, idp->data, idp->len);
1832 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1833 0, packet->data, packet->len, FALSE);
1835 silc_buffer_free(packet);
1836 silc_buffer_free(idp);
1837 silc_free(channel_id);
1840 silc_server_command_free(cmd);
1843 /* Server side of INVITE command. Invites some client to join some channel. */
1845 SILC_SERVER_CMD_FUNC(invite)
1847 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1848 SilcServer server = cmd->server;
1849 SilcSocketConnection sock = cmd->sock, dest_sock;
1850 SilcClientEntry sender, dest;
1851 SilcClientID *dest_id;
1852 SilcChannelEntry channel;
1853 SilcChannelID *channel_id;
1858 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1860 /* Get destination ID */
1861 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1863 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1864 SILC_STATUS_ERR_NO_CLIENT_ID);
1867 dest_id = silc_id_payload_parse_id(tmp, len);
1869 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1870 SILC_STATUS_ERR_NO_CLIENT_ID);
1874 /* Get Channel ID */
1875 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1877 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1878 SILC_STATUS_ERR_NO_CHANNEL_ID);
1881 channel_id = silc_id_payload_parse_id(tmp, len);
1883 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1884 SILC_STATUS_ERR_NO_CHANNEL_ID);
1888 /* Check whether the channel exists */
1889 channel = silc_idlist_find_channel_by_id(server->local_list,
1892 channel = silc_idlist_find_channel_by_id(server->global_list,
1895 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1896 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1901 /* Check whether the sender of this command is on the channel. */
1902 sender = (SilcClientEntry)sock->user_data;
1903 if (!silc_server_client_on_channel(sender, channel)) {
1904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1905 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1909 /* Check whether the channel is invite-only channel. If yes then the
1910 sender of this command must be at least channel operator. */
1911 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1912 SilcChannelClientEntry chl;
1914 silc_list_start(channel->user_list);
1915 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1916 if (chl->client == sender) {
1917 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1918 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1919 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1926 /* Find the connection data for the destination. If it is local we will
1927 send it directly otherwise we will send it to router for routing. */
1928 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1930 dest_sock = (SilcSocketConnection)dest->connection;
1932 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1934 /* Check whether the requested client is already on the channel. */
1935 /* XXX if we are normal server we don't know about global clients on
1936 the channel thus we must request it (USERS command), check from
1937 local cache as well. */
1938 if (silc_server_client_on_channel(dest, channel)) {
1939 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1940 SILC_STATUS_ERR_USER_ON_CHANNEL);
1944 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1946 /* Send notify to the client that is invited to the channel */
1947 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1949 SILC_NOTIFY_TYPE_INVITE, 2,
1950 sidp->data, sidp->len, tmp, len);
1952 /* Send command reply */
1953 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1956 silc_buffer_free(sidp);
1959 silc_server_command_free(cmd);
1964 SilcSocketConnection sock;
1968 /* Quits connection to client. This gets called if client won't
1969 close the connection even when it has issued QUIT command. */
1971 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1973 QuitInternal q = (QuitInternal)context;
1975 /* Free all client specific data, such as client entry and entires
1976 on channels this client may be on. */
1977 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1979 q->sock->user_data = NULL;
1981 /* Close the connection on our side */
1982 silc_server_close_connection(q->server, q->sock);
1984 silc_free(q->signoff);
1988 /* Quits SILC session. This is the normal way to disconnect client. */
1990 SILC_SERVER_CMD_FUNC(quit)
1992 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1993 SilcServer server = cmd->server;
1994 SilcSocketConnection sock = cmd->sock;
1996 unsigned char *tmp = NULL;
1997 unsigned int len = 0;
1999 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2001 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2004 /* Get destination ID */
2005 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2009 q = silc_calloc(1, sizeof(*q));
2012 q->signoff = tmp ? strdup(tmp) : NULL;
2014 /* We quit the connection with little timeout */
2015 silc_task_register(server->timeout_queue, sock->sock,
2016 silc_server_command_quit_cb, (void *)q,
2017 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2020 silc_server_command_free(cmd);
2023 /* Server side of command KILL. This command is used by router operator
2024 to remove an client from the SILC Network temporarily. */
2026 SILC_SERVER_CMD_FUNC(kill)
2028 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2029 SilcServer server = cmd->server;
2030 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2031 SilcClientEntry remote_client;
2032 SilcClientID *client_id;
2033 unsigned char *tmp, *comment;
2034 unsigned int tmp_len, tmp_len2;
2036 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2038 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2041 /* KILL command works only on router */
2042 if (server->server_type != SILC_ROUTER) {
2043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2044 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2048 /* Check whether client has the permissions. */
2049 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2051 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2055 /* Get the client ID */
2056 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2058 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2059 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2062 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2064 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2065 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2069 /* Get the client entry */
2070 remote_client = silc_idlist_find_client_by_id(server->local_list,
2072 if (!remote_client) {
2073 remote_client = silc_idlist_find_client_by_id(server->global_list,
2075 if (!remote_client) {
2076 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2077 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2083 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2087 /* Send reply to the sender */
2088 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2091 /* Send the KILL notify packets. First send it to the channel, then
2092 to our primary router and then directly to the client who is being
2093 killed right now. */
2095 /* Send KILLED notify to the channels. It is not sent to the client
2096 as it will be sent differently destined directly to the client and not
2098 silc_server_send_notify_on_channels(server, remote_client,
2099 remote_client, SILC_NOTIFY_TYPE_KILLED,
2102 comment, comment ? tmp_len2 : 0);
2104 /* Send KILLED notify to primary route */
2105 if (!server->standalone)
2106 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2107 remote_client->id, SILC_ID_CLIENT_LEN,
2110 /* Send KILLED notify to the client directly */
2111 silc_server_send_notify_killed(server, remote_client->connection ?
2112 remote_client->connection :
2113 remote_client->router->connection, FALSE,
2114 remote_client->id, SILC_ID_CLIENT_LEN,
2117 /* Remove the client from all channels. This generates new keys to the
2118 channels as well. */
2119 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2122 /* Remove the client entry, If it is locally connected then we will also
2123 disconnect the client here */
2124 if (remote_client->data.registered && remote_client->connection) {
2125 /* Remove locally conneted client */
2126 SilcSocketConnection sock = remote_client->connection;
2127 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2128 silc_server_close_connection(server, sock);
2130 /* Remove remote client */
2131 if (!silc_idlist_del_client(server->global_list, remote_client))
2132 silc_idlist_del_client(server->local_list, remote_client);
2136 silc_server_command_free(cmd);
2139 /* Server side of command INFO. This sends information about us to
2140 the client. If client requested specific server we will send the
2141 command to that server. */
2143 SILC_SERVER_CMD_FUNC(info)
2145 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2146 SilcServer server = cmd->server;
2147 SilcBuffer packet, idp;
2148 char info_string[256], *dest_server;
2150 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
2152 /* Get server name */
2153 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2155 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2156 SILC_STATUS_ERR_NO_SUCH_SERVER);
2160 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2161 /* Send our reply */
2162 memset(info_string, 0, sizeof(info_string));
2163 snprintf(info_string, sizeof(info_string),
2164 "location: %s server: %s admin: %s <%s>",
2165 server->config->admin_info->location,
2166 server->config->admin_info->server_type,
2167 server->config->admin_info->admin_name,
2168 server->config->admin_info->admin_email);
2170 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2172 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2173 SILC_STATUS_OK, 0, 2,
2174 2, idp->data, idp->len,
2176 strlen(info_string));
2177 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2178 packet->data, packet->len, FALSE);
2180 silc_buffer_free(packet);
2181 silc_buffer_free(idp);
2183 /* Send this command to the requested server */
2185 if (server->server_type == SILC_SERVER && !server->standalone) {
2189 if (server->server_type == SILC_ROUTER) {
2195 silc_server_command_free(cmd);
2198 /* Server side of command PING. This just replies to the ping. */
2200 SILC_SERVER_CMD_FUNC(ping)
2202 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2203 SilcServer server = cmd->server;
2208 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2211 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2214 SILC_STATUS_ERR_NO_SERVER_ID);
2217 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2221 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2222 /* Send our reply */
2223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2226 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2227 SILC_STATUS_ERR_NO_SUCH_SERVER);
2234 silc_server_command_free(cmd);
2237 /* Internal routine to join channel. The channel sent to this function
2238 has been either created or resolved from ID lists. This joins the sent
2239 client to the channel. */
2241 static void silc_server_command_join_channel(SilcServer server,
2242 SilcServerCommandContext cmd,
2243 SilcChannelEntry channel,
2244 SilcClientID *client_id,
2248 SilcSocketConnection sock = cmd->sock;
2250 unsigned int tmp_len, user_count;
2251 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2252 SilcClientEntry client;
2253 SilcChannelClientEntry chl;
2254 SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
2255 unsigned short ident = silc_command_get_ident(cmd->payload);
2257 SILC_LOG_DEBUG(("Start"));
2262 /* Get passphrase */
2263 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2265 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2266 memcpy(passphrase, tmp, tmp_len);
2270 * Check channel modes
2273 /* Check invite list if channel is invite-only channel */
2274 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2275 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2276 /* Invite list is specified. Check whether client is invited in the
2277 list. If not, then check whether it has been invited otherwise. */
2280 /* XXX client must be invited to be able to join the channel */
2284 /* Check ban list if set */
2285 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2289 /* Check the channel passphrase if set. */
2290 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2291 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
2292 strlen(channel->mode_data.passphrase))) {
2293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2294 SILC_STATUS_ERR_BAD_PASSWORD);
2299 /* Check user count limit if set. */
2300 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2301 if (silc_list_count(channel->user_list) + 1 >
2302 channel->mode_data.user_limit) {
2303 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2304 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2310 * Client is allowed to join to the channel. Make it happen.
2313 /* Get the client entry */
2314 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2315 client = (SilcClientEntry)sock->user_data;
2317 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2320 /* XXX actually this is useless since router finds always cell's
2321 local clients from its local lists. */
2322 client = silc_idlist_find_client_by_id(server->global_list, client_id,
2329 /* Check whether the client already is on the channel */
2330 if (silc_server_client_on_channel(client, channel)) {
2331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2332 SILC_STATUS_ERR_USER_ON_CHANNEL);
2336 /* Generate new channel key as protocol dictates */
2337 if ((!created && silc_list_count(channel->user_list) > 0) ||
2338 !channel->channel_key)
2339 silc_server_create_channel_key(server, channel, 0);
2341 /* Send the channel key. This is broadcasted to the channel but is not
2342 sent to the client who is joining to the channel. */
2343 silc_server_send_channel_key(server, NULL, channel,
2344 server->server_type == SILC_ROUTER ?
2345 FALSE : !server->standalone);
2347 /* Join the client to the channel by adding it to channel's user list.
2348 Add also the channel to client entry's channels list for fast cross-
2350 chl = silc_calloc(1, sizeof(*chl));
2352 chl->client = client;
2353 chl->channel = channel;
2354 silc_list_add(channel->user_list, chl);
2355 silc_list_add(client->channels, chl);
2357 /* Get users on the channel */
2358 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2361 /* Encode Client ID Payload of the original client who wants to join */
2362 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2364 /* Encode command reply packet */
2365 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2366 SILC_PUT32_MSB(channel->mode, mode);
2367 SILC_PUT32_MSB(created, tmp2);
2368 SILC_PUT32_MSB(user_count, tmp3);
2369 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2370 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2371 strlen(channel->channel_key->
2373 channel->channel_key->cipher->name,
2374 channel->key_len / 8, channel->key);
2376 if (!channel->topic) {
2378 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2379 SILC_STATUS_OK, ident, 9,
2380 2, channel->channel_name,
2381 strlen(channel->channel_name),
2382 3, chidp->data, chidp->len,
2383 4, clidp->data, clidp->len,
2386 7, keyp->data, keyp->len,
2388 13, user_list->data, user_list->len,
2389 14, mode_list->data,
2393 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2394 SILC_STATUS_OK, ident, 10,
2395 2, channel->channel_name,
2396 strlen(channel->channel_name),
2397 3, chidp->data, chidp->len,
2398 4, clidp->data, clidp->len,
2401 7, keyp->data, keyp->len,
2403 strlen(channel->topic),
2405 13, user_list->data, user_list->len,
2406 14, mode_list->data,
2410 /* Send command reply */
2411 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2412 reply->data, reply->len, FALSE);
2414 if (!cmd->pending) {
2415 /* Send JOIN notify to locally connected clients on the channel */
2416 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2417 SILC_NOTIFY_TYPE_JOIN, 2,
2418 clidp->data, clidp->len,
2419 chidp->data, chidp->len);
2421 /* Send JOIN notify packet to our primary router */
2422 if (!server->standalone)
2423 silc_server_send_notify_join(server, server->router->connection,
2424 server->server_type == SILC_ROUTER ?
2425 TRUE : FALSE, channel, client->id,
2426 SILC_ID_CLIENT_LEN);
2429 silc_buffer_free(reply);
2430 silc_buffer_free(clidp);
2431 silc_buffer_free(chidp);
2432 silc_buffer_free(keyp);
2433 silc_buffer_free(user_list);
2434 silc_buffer_free(mode_list);
2438 silc_free(passphrase);
2441 /* Server side of command JOIN. Joins client into requested channel. If
2442 the channel does not exist it will be created. */
2444 SILC_SERVER_CMD_FUNC(join)
2446 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2447 SilcServer server = cmd->server;
2449 char *tmp, *channel_name = NULL, *cipher, *hmac;
2450 SilcChannelEntry channel;
2451 unsigned int umode = 0;
2452 int created = FALSE;
2453 SilcClientID *client_id;
2455 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2457 /* Get channel name */
2458 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2461 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2466 if (strlen(channel_name) > 256)
2467 channel_name[255] = '\0';
2469 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2470 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2471 SILC_STATUS_ERR_BAD_CHANNEL);
2472 silc_free(channel_name);
2476 /* Get Client ID of the client who is joining to the channel */
2477 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2480 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2483 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2485 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2486 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2490 /* Get cipher and hmac name */
2491 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2492 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2494 /* See if the channel exists */
2495 channel = silc_idlist_find_channel_by_name(server->local_list,
2496 channel_name, NULL);
2498 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2499 /* If this is coming from client the Client ID in the command packet must
2500 be same as the client's ID. */
2501 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2502 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2503 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2505 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2511 /* Channel not found */
2513 /* If we are standalone server we don't have a router, we just create
2514 the channel by ourselves. */
2515 if (server->standalone) {
2516 channel = silc_server_create_new_channel(server, server->id, cipher,
2517 hmac, channel_name, TRUE);
2518 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2523 /* The channel does not exist on our server. If we are normal server
2524 we will send JOIN command to our router which will handle the
2525 joining procedure (either creates the channel if it doesn't exist
2526 or joins the client to it). */
2527 if (server->server_type == SILC_SERVER) {
2529 unsigned short old_ident;
2531 old_ident = silc_command_get_ident(cmd->payload);
2532 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2533 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2535 /* Send JOIN command to our router */
2536 silc_server_packet_send(server, (SilcSocketConnection)
2537 server->router->connection,
2538 SILC_PACKET_COMMAND, cmd->packet->flags,
2539 tmpbuf->data, tmpbuf->len, TRUE);
2541 /* Reprocess this packet after received reply from router */
2542 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2543 silc_command_get_ident(cmd->payload),
2544 silc_server_command_destructor,
2545 silc_server_command_join,
2546 silc_server_command_dup(cmd));
2547 cmd->pending = TRUE;
2551 /* We are router and the channel does not seem exist so we will check
2552 our global list as well for the channel. */
2553 channel = silc_idlist_find_channel_by_name(server->global_list,
2554 channel_name, NULL);
2556 /* Channel really does not exist, create it */
2557 channel = silc_server_create_new_channel(server, server->id, cipher,
2558 hmac, channel_name, TRUE);
2559 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2566 /* Channel not found */
2568 /* If the command came from router and/or we are normal server then
2569 something went wrong with the joining as the channel was not found.
2570 We can't do anything else but ignore this. */
2571 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2572 server->server_type == SILC_SERVER)
2575 /* We are router and the channel does not seem exist so we will check
2576 our global list as well for the channel. */
2577 channel = silc_idlist_find_channel_by_name(server->global_list,
2578 channel_name, NULL);
2580 /* Channel really does not exist, create it */
2581 channel = silc_server_create_new_channel(server, server->id, cipher,
2582 hmac, channel_name, TRUE);
2583 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2589 /* If the channel does not have global users and is also empty it means the
2590 channel was created globally (by our router) and the client will be the
2591 channel founder and operator. */
2592 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2593 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2594 created = TRUE; /* Created globally by our router */
2597 /* Join to the channel */
2598 silc_server_command_join_channel(server, cmd, channel, client_id,
2601 silc_free(client_id);
2604 silc_server_command_free(cmd);
2607 /* Server side of command MOTD. Sends server's current "message of the
2608 day" to the client. */
2610 SILC_SERVER_CMD_FUNC(motd)
2612 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2613 SilcServer server = cmd->server;
2617 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2619 /* XXX show currently only our motd */
2621 if (server->config && server->config->motd &&
2622 server->config->motd->motd_file) {
2625 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2630 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2641 silc_server_command_free(cmd);
2644 /* Server side of command UMODE. Client can use this command to set/unset
2645 user mode. Client actually cannot set itself to be as server/router
2646 operator so this can be used only to unset the modes. */
2648 SILC_SERVER_CMD_FUNC(umode)
2650 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2651 SilcServer server = cmd->server;
2652 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2654 unsigned char *tmp_mask;
2656 unsigned short ident = silc_command_get_ident(cmd->payload);
2658 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2661 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
2663 /* Get the client's mode mask */
2664 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2666 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2667 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2670 SILC_GET32_MSB(mask, tmp_mask);
2676 if (mask & SILC_UMODE_SERVER_OPERATOR) {
2677 /* Cannot operator mode */
2678 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2679 SILC_STATUS_ERR_PERM_DENIED);
2682 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
2683 /* Remove the server operator rights */
2684 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
2687 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
2688 /* Cannot operator mode */
2689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2690 SILC_STATUS_ERR_PERM_DENIED);
2693 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
2694 /* Remove the router operator rights */
2695 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
2698 /* Send command reply to sender */
2699 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
2700 SILC_STATUS_OK, ident, 1,
2702 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2703 packet->data, packet->len, FALSE);
2704 silc_buffer_free(packet);
2707 silc_server_command_free(cmd);
2710 /* Checks that client has rights to add or remove channel modes. If any
2711 of the checks fails FALSE is returned. */
2713 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2714 SilcChannelClientEntry client,
2717 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2718 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2720 /* Check whether has rights to change anything */
2721 if (!is_op && !is_fo)
2724 /* Check whether has rights to change everything */
2728 /* We know that client is channel operator, check that they are not
2729 changing anything that requires channel founder rights. Rest of the
2730 modes are available automatically for channel operator. */
2732 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2733 if (is_op && !is_fo)
2736 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2737 if (is_op && !is_fo)
2742 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2743 if (is_op && !is_fo)
2746 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2747 if (is_op && !is_fo)
2752 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2753 if (is_op && !is_fo)
2756 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2757 if (is_op && !is_fo)
2765 /* Server side command of CMODE. Changes channel mode */
2767 SILC_SERVER_CMD_FUNC(cmode)
2769 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2770 SilcServer server = cmd->server;
2771 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2772 SilcChannelID *channel_id;
2773 SilcChannelEntry channel;
2774 SilcChannelClientEntry chl;
2775 SilcBuffer packet, cidp;
2776 unsigned char *tmp, *tmp_id, *tmp_mask;
2777 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2778 unsigned short ident = silc_command_get_ident(cmd->payload);
2780 SILC_LOG_DEBUG(("Start"));
2782 argc = silc_argument_get_arg_num(cmd->args);
2784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2785 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2789 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2790 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2794 /* Get Channel ID */
2795 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2797 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2798 SILC_STATUS_ERR_NO_CHANNEL_ID);
2801 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2803 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2804 SILC_STATUS_ERR_NO_CHANNEL_ID);
2808 /* Get the channel mode mask */
2809 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2812 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2815 SILC_GET32_MSB(mode_mask, tmp_mask);
2817 /* Get channel entry */
2818 channel = silc_idlist_find_channel_by_id(server->local_list,
2821 channel = silc_idlist_find_channel_by_id(server->global_list,
2824 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2825 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2830 /* Check whether this client is on the channel */
2831 if (!silc_server_client_on_channel(client, channel)) {
2832 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2833 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2837 /* Get entry to the channel user list */
2838 silc_list_start(channel->user_list);
2839 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2840 if (chl->client == client)
2843 /* Check that client has rights to change any requested channel modes */
2844 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2845 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2846 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2851 * Check the modes. Modes that requires nothing special operation are
2855 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2856 /* Channel uses private keys to protect traffic. Client(s) has set the
2857 key locally they want to use, server does not know that key. */
2858 /* Nothing interesting to do here now */
2860 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2861 /* The mode is removed and we need to generate and distribute
2862 new channel key. Clients are not using private channel keys
2863 anymore after this. */
2865 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2868 /* Re-generate channel key */
2869 silc_server_create_channel_key(server, channel, 0);
2871 /* Encode channel key payload to be distributed on the channel */
2873 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2874 strlen(channel->channel_key->
2876 channel->channel_key->cipher->name,
2877 channel->key_len / 8, channel->key);
2879 /* If we are normal server then we will send it to our router. If we
2880 are router we will send it to all local servers that has clients on
2882 if (server->server_type == SILC_SERVER) {
2883 if (!server->standalone)
2884 silc_server_packet_send(server,
2885 cmd->server->router->connection,
2886 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2892 /* Send to locally connected clients on the channel */
2893 silc_server_packet_send_local_channel(server, channel,
2894 SILC_PACKET_CHANNEL_KEY, 0,
2895 packet->data, packet->len, FALSE);
2896 silc_buffer_free(packet);
2900 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2901 /* User limit is set on channel */
2902 unsigned int user_limit;
2904 /* Get user limit */
2905 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2907 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2908 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2909 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2913 SILC_GET32_MSB(user_limit, tmp);
2914 channel->mode_data.user_limit = user_limit;
2917 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2918 /* User limit mode is unset. Remove user limit */
2919 channel->mode_data.user_limit = 0;
2922 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2923 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2924 /* Passphrase has been set to channel */
2926 /* Get the passphrase */
2927 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2930 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2934 /* Save the passphrase */
2935 channel->mode_data.passphrase = strdup(tmp);
2938 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2939 /* Passphrase mode is unset. remove the passphrase */
2940 if (channel->mode_data.passphrase) {
2941 silc_free(channel->mode_data.passphrase);
2942 channel->mode_data.passphrase = NULL;
2947 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2948 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2949 /* Ban list is specified for channel */
2952 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2955 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2959 /* XXX check that channel founder is not banned */
2961 /* Save the ban list */
2962 channel->mode_data.ban_list = strdup(tmp);
2965 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2966 /* Ban mode is unset. Remove the entire ban list */
2967 if (channel->mode_data.ban_list) {
2968 silc_free(channel->mode_data.ban_list);
2969 channel->mode_data.ban_list = NULL;
2974 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2975 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2976 /* Invite list is specified for channel */
2978 /* Get invite list */
2979 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2982 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2986 /* Save the invite linst */
2987 channel->mode_data.invite_list = strdup(tmp);
2990 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2991 /* Invite list mode is unset. Remove the entire invite list */
2992 if (channel->mode_data.invite_list) {
2993 silc_free(channel->mode_data.invite_list);
2994 channel->mode_data.invite_list = NULL;
2999 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3000 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3001 /* Cipher to use protect the traffic */
3002 unsigned int key_len;
3005 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
3007 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3008 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3012 /* XXX Duplicated code, make own function for this!! */
3014 /* Delete old cipher and allocate the new one */
3015 silc_cipher_free(channel->channel_key);
3016 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
3017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3018 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3021 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
3023 /* Re-generate channel key */
3024 silc_server_create_channel_key(server, channel, key_len);
3026 /* Encode channel key payload to be distributed on the channel */
3028 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3029 strlen(channel->channel_key->
3031 channel->channel_key->cipher->name,
3032 channel->key_len / 8, channel->key);
3034 /* If we are normal server then we will send it to our router. If we
3035 are router we will send it to all local servers that has clients on
3037 if (server->server_type == SILC_SERVER) {
3038 if (!server->standalone)
3039 silc_server_packet_send(server,
3040 cmd->server->router->connection,
3041 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3047 /* Send to locally connected clients on the channel */
3048 silc_server_packet_send_local_channel(server, channel,
3049 SILC_PACKET_CHANNEL_KEY, 0,
3050 packet->data, packet->len, FALSE);
3051 silc_buffer_free(packet);
3054 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3055 /* Cipher mode is unset. Remove the cipher and revert back to
3058 if (channel->mode_data.cipher) {
3059 silc_free(channel->mode_data.cipher);
3060 channel->mode_data.cipher = NULL;
3061 channel->mode_data.key_len = 0;
3064 /* Generate new cipher and key for the channel */
3066 /* XXX Duplicated code, make own function for this!! */
3068 /* Delete old cipher and allocate default one */
3069 silc_cipher_free(channel->channel_key);
3070 if (!channel->cipher)
3071 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
3073 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
3074 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3075 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3080 /* Re-generate channel key */
3081 silc_server_create_channel_key(server, channel, 0);
3083 /* Encode channel key payload to be distributed on the channel */
3085 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3086 strlen(channel->channel_key->
3088 channel->channel_key->cipher->name,
3089 channel->key_len / 8, channel->key);
3091 /* If we are normal server then we will send it to our router. If we
3092 are router we will send it to all local servers that has clients on
3094 if (server->server_type == SILC_SERVER) {
3095 if (!server->standalone)
3096 silc_server_packet_send(server,
3097 cmd->server->router->connection,
3098 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3104 /* Send to locally connected clients on the channel */
3105 silc_server_packet_send_local_channel(server, channel,
3106 SILC_PACKET_CHANNEL_KEY, 0,
3107 packet->data, packet->len, FALSE);
3108 silc_buffer_free(packet);
3112 /* Finally, set the mode */
3113 channel->mode = mode_mask;
3115 /* Send CMODE_CHANGE notify */
3116 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3117 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3118 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
3119 cidp->data, cidp->len,
3122 /* Set CMODE notify type to network */
3123 if (!server->standalone)
3124 silc_server_send_notify_cmode(server, server->router->connection,
3125 server->server_type == SILC_ROUTER ?
3126 TRUE : FALSE, channel,
3127 mode_mask, client->id, SILC_ID_CLIENT_LEN);
3129 /* Send command reply to sender */
3130 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3131 SILC_STATUS_OK, ident, 1,
3133 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3134 packet->data, packet->len, FALSE);
3136 silc_buffer_free(packet);
3137 silc_free(channel_id);
3141 silc_server_command_free(cmd);
3144 /* Server side of CUMODE command. Changes client's mode on a channel. */
3146 SILC_SERVER_CMD_FUNC(cumode)
3148 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3149 SilcServer server = cmd->server;
3150 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3151 SilcChannelID *channel_id;
3152 SilcClientID *client_id;
3153 SilcChannelEntry channel;
3154 SilcClientEntry target_client;
3155 SilcChannelClientEntry chl;
3156 SilcBuffer packet, idp;
3157 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3158 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3160 unsigned short ident = silc_command_get_ident(cmd->payload);
3162 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3164 /* Get Channel ID */
3165 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3168 SILC_STATUS_ERR_NO_CHANNEL_ID);
3171 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3173 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3174 SILC_STATUS_ERR_NO_CHANNEL_ID);
3178 /* Get channel entry */
3179 channel = silc_idlist_find_channel_by_id(server->local_list,
3182 channel = silc_idlist_find_channel_by_id(server->global_list,
3185 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3186 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3191 /* Check whether sender is on the channel */
3192 if (!silc_server_client_on_channel(client, channel)) {
3193 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3194 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3198 /* Check that client has rights to change other's rights */
3199 silc_list_start(channel->user_list);
3200 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3201 if (chl->client == client) {
3202 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3203 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3205 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3209 sender_mask = chl->mode;
3214 /* Get the target client's channel mode mask */
3215 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3218 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3221 SILC_GET32_MSB(target_mask, tmp_mask);
3223 /* Get target Client ID */
3224 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3226 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3227 SILC_STATUS_ERR_NO_CLIENT_ID);
3230 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3233 SILC_STATUS_ERR_NO_CLIENT_ID);
3237 /* Get target client's entry */
3238 target_client = silc_idlist_find_client_by_id(server->local_list,
3240 if (!target_client) {
3241 target_client = silc_idlist_find_client_by_id(server->global_list,
3245 /* Check whether target client is on the channel */
3246 if (!silc_server_client_on_channel(target_client, channel)) {
3247 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3248 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3252 /* Get entry to the channel user list */
3253 silc_list_start(channel->user_list);
3254 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3255 if (chl->client == target_client)
3262 /* If the target client is founder, no one else can change their mode
3264 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3266 SILC_STATUS_ERR_NOT_YOU);
3270 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3271 /* Cannot promote anyone to channel founder */
3272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3273 SILC_STATUS_ERR_NOT_YOU);
3276 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3277 if (target_client == client) {
3278 /* Remove channel founder rights from itself */
3279 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3282 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3283 SILC_STATUS_ERR_NOT_YOU);
3289 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3290 /* Promote to operator */
3291 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3292 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3296 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3297 /* Demote to normal user */
3298 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3303 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3305 /* Send notify to channel, notify only if mode was actually changed. */
3307 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3308 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3309 idp->data, idp->len,
3313 /* Set CUMODE notify type to network */
3314 if (!server->standalone)
3315 silc_server_send_notify_cumode(server, server->router->connection,
3316 server->server_type == SILC_ROUTER ?
3317 TRUE : FALSE, channel,
3318 target_mask, client->id,
3321 SILC_ID_CLIENT_LEN);
3324 /* Send command reply to sender */
3325 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3326 SILC_STATUS_OK, ident, 2,
3328 3, tmp_id, tmp_len);
3329 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3330 packet->data, packet->len, FALSE);
3332 silc_buffer_free(packet);
3333 silc_free(channel_id);
3334 silc_free(client_id);
3335 silc_buffer_free(idp);
3338 silc_server_command_free(cmd);
3341 /* Server side of KICK command. Kicks client out of channel. */
3343 SILC_SERVER_CMD_FUNC(kick)
3345 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3346 SilcServer server = cmd->server;
3347 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3348 SilcClientEntry target_client;
3349 SilcChannelID *channel_id;
3350 SilcClientID *client_id;
3351 SilcChannelEntry channel;
3352 SilcChannelClientEntry chl;
3354 unsigned int tmp_len;
3355 unsigned char *tmp, *comment;
3357 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3359 /* Get Channel ID */
3360 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3362 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3363 SILC_STATUS_ERR_NO_CHANNEL_ID);
3366 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3369 SILC_STATUS_ERR_NO_CHANNEL_ID);
3373 /* Get channel entry */
3374 channel = silc_idlist_find_channel_by_id(server->local_list,
3377 channel = silc_idlist_find_channel_by_id(server->local_list,
3380 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3381 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3386 /* Check whether sender is on the channel */
3387 if (!silc_server_client_on_channel(client, channel)) {
3388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3389 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3393 /* Check that the kicker is channel operator or channel founder */
3394 silc_list_start(channel->user_list);
3395 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3396 if (chl->client == client) {
3397 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3398 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3399 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3406 /* Get target Client ID */
3407 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3410 SILC_STATUS_ERR_NO_CLIENT_ID);
3413 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3416 SILC_STATUS_ERR_NO_CLIENT_ID);
3420 /* Get target client's entry */
3421 target_client = silc_idlist_find_client_by_id(server->local_list,
3423 if (!target_client) {
3424 target_client = silc_idlist_find_client_by_id(server->global_list,
3428 /* Check that the target client is not channel founder. Channel founder
3429 cannot be kicked from the channel. */
3430 silc_list_start(channel->user_list);
3431 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3432 if (chl->client == target_client) {
3433 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3435 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3442 /* Check whether target client is on the channel */
3443 if (!silc_server_client_on_channel(target_client, channel)) {
3444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3445 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3451 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3455 /* Send command reply to sender */
3456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3459 /* Send KICKED notify to local clients on the channel */
3460 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3461 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3462 SILC_NOTIFY_TYPE_KICKED,
3464 idp->data, idp->len,
3465 comment, comment ? strlen(comment) : 0);
3466 silc_buffer_free(idp);
3468 /* Remove the client from the channel. If the channel does not exist
3469 after removing the client then the client kicked itself off the channel
3470 and we don't have to send anything after that. */
3471 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3472 target_client, FALSE))
3475 /* Send KICKED notify to primary route */
3476 if (!server->standalone)
3477 silc_server_send_notify_kicked(server, server->router->connection,
3478 server->server_type == SILC_ROUTER ?
3479 TRUE : FALSE, channel,
3480 target_client->id, SILC_ID_CLIENT_LEN,
3483 /* Re-generate channel key */
3484 silc_server_create_channel_key(server, channel, 0);
3486 /* Send the channel key to the channel. The key of course is not sent
3487 to the client who was kicked off the channel. */
3488 silc_server_send_channel_key(server, target_client->connection, channel,
3489 server->server_type == SILC_ROUTER ?
3490 FALSE : !server->standalone);
3493 silc_server_command_free(cmd);
3496 /* Server side of OPER command. Client uses this comand to obtain server
3497 operator privileges to this server/router. */
3499 SILC_SERVER_CMD_FUNC(oper)
3501 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3502 SilcServer server = cmd->server;
3503 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3504 unsigned char *username, *auth;
3505 unsigned int tmp_len;
3506 SilcServerConfigSectionAdminConnection *admin;
3507 SilcIDListData idata = (SilcIDListData)client;
3509 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
3511 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3514 /* Get the username */
3515 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3517 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3518 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3522 /* Get the admin configuration */
3523 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3524 username, client->nickname);
3526 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3527 username, client->nickname);
3529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3530 SILC_STATUS_ERR_AUTH_FAILED);
3535 /* Get the authentication payload */
3536 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3538 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3539 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3543 /* Verify the authentication data */
3544 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3545 admin->auth_data, admin->auth_data_len,
3546 idata->hash, client->id, SILC_ID_CLIENT)) {
3547 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3548 SILC_STATUS_ERR_AUTH_FAILED);
3552 /* Client is now server operator */
3553 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3555 /* Send reply to the sender */
3556 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3560 silc_server_command_free(cmd);
3563 /* Server side of SILCOPER command. Client uses this comand to obtain router
3564 operator privileges to this router. */
3566 SILC_SERVER_CMD_FUNC(silcoper)
3568 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3569 SilcServer server = cmd->server;
3570 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3571 unsigned char *username, *auth;
3572 unsigned int tmp_len;
3573 SilcServerConfigSectionAdminConnection *admin;
3574 SilcIDListData idata = (SilcIDListData)client;
3576 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
3578 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3581 /* Get the username */
3582 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3584 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3585 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3589 /* Get the admin configuration */
3590 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3591 username, client->nickname);
3593 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3594 username, client->nickname);
3596 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3597 SILC_STATUS_ERR_AUTH_FAILED);
3602 /* Get the authentication payload */
3603 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3605 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3606 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3610 /* Verify the authentication data */
3611 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3612 admin->auth_data, admin->auth_data_len,
3613 idata->hash, client->id, SILC_ID_CLIENT)) {
3614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3615 SILC_STATUS_ERR_AUTH_FAILED);
3619 /* Client is now router operator */
3620 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
3622 /* Send reply to the sender */
3623 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3627 silc_server_command_free(cmd);
3630 /* Server side command of CONNECT. Connects us to the specified remote
3631 server or router. */
3633 SILC_SERVER_CMD_FUNC(connect)
3635 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3636 SilcServer server = cmd->server;
3637 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3638 unsigned char *tmp, *host;
3639 unsigned int tmp_len;
3640 unsigned int port = SILC_PORT;
3642 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
3644 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3647 /* Check whether client has the permissions. */
3648 if (client->mode == SILC_UMODE_NONE) {
3649 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3650 SILC_STATUS_ERR_NO_SERVER_PRIV);
3654 if (server->server_type == SILC_ROUTER &&
3655 client->mode & SILC_UMODE_SERVER_OPERATOR) {
3656 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3657 SILC_STATUS_ERR_NO_ROUTER_PRIV);
3661 /* Get the remote server */
3662 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3664 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3665 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3670 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3672 SILC_GET32_MSB(port, tmp);
3674 /* Create the connection. It is done with timeout and is async. */
3675 silc_server_create_connection(server, host, port);
3677 /* Send reply to the sender */
3678 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3682 silc_server_command_free(cmd);
3685 SILC_SERVER_CMD_FUNC(restart)
3689 /* Server side command of CLOSE. Closes connection to a specified server. */
3691 SILC_SERVER_CMD_FUNC(close)
3693 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3694 SilcServer server = cmd->server;
3695 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3696 SilcServerEntry server_entry;
3697 SilcSocketConnection sock;
3699 unsigned int tmp_len;
3700 unsigned char *name;
3701 unsigned int port = SILC_PORT;
3703 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3705 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3708 /* Check whether client has the permissions. */
3709 if (client->mode == SILC_UMODE_NONE) {
3710 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3711 SILC_STATUS_ERR_NO_SERVER_PRIV);
3715 /* Get the remote server */
3716 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3719 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3724 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3726 SILC_GET32_MSB(port, tmp);
3728 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3730 if (!server_entry) {
3731 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3732 SILC_STATUS_ERR_NO_SERVER_ID);
3736 /* Send reply to the sender */
3737 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3740 /* Close the connection to the server */
3741 sock = (SilcSocketConnection)server_entry->connection;
3742 silc_server_free_sock_user_data(server, sock);
3743 silc_server_close_connection(server, sock);
3746 silc_server_command_free(cmd);
3749 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3750 active connections. */
3752 SILC_SERVER_CMD_FUNC(shutdown)
3754 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3755 SilcServer server = cmd->server;
3756 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3758 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3760 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3763 /* Check whether client has the permission. */
3764 if (client->mode == SILC_UMODE_NONE) {
3765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3766 SILC_STATUS_ERR_NO_SERVER_PRIV);
3770 /* Send reply to the sender */
3771 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3774 /* Then, gracefully, or not, bring the server down. */
3775 silc_server_stop(server);
3779 silc_server_command_free(cmd);
3782 /* Server side command of LEAVE. Removes client from a channel. */
3784 SILC_SERVER_CMD_FUNC(leave)
3786 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3787 SilcServer server = cmd->server;
3788 SilcSocketConnection sock = cmd->sock;
3789 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3791 SilcChannelEntry channel;
3793 unsigned int i, len;
3796 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3798 /* Get Channel ID */
3799 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3802 SILC_STATUS_ERR_NO_CHANNEL_ID);
3805 id = silc_id_payload_parse_id(tmp, len);
3807 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3808 SILC_STATUS_ERR_NO_CHANNEL_ID);
3812 /* Get channel entry */
3813 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3815 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3818 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3823 /* Check whether this client is on the channel */
3824 if (!silc_server_client_on_channel(id_entry, channel)) {
3825 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3826 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3830 /* Notify routers that they should remove this client from their list
3831 of clients on the channel. Send LEAVE notify type. */
3832 if (!server->standalone)
3833 silc_server_send_notify_leave(server, server->router->connection,
3834 server->server_type == SILC_ROUTER ?
3835 TRUE : FALSE, channel, id_entry->id,
3836 SILC_ID_CLIENT_LEN);
3838 /* Remove client from channel */
3839 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3844 /* If the channel does not exist anymore we won't send anything */
3848 /* Re-generate channel key */
3849 silc_server_create_channel_key(server, channel, 0);
3851 /* Encode channel key payload to be distributed on the channel */
3853 silc_channel_key_payload_encode(len, tmp,
3854 strlen(channel->channel_key->cipher->name),
3855 channel->channel_key->cipher->name,
3856 channel->key_len / 8, channel->key);
3858 /* If we are normal server then we will send it to our router. If we
3859 are router we will send it to all local servers that has clients on
3861 if (server->server_type == SILC_SERVER) {
3862 if (!server->standalone)
3863 silc_server_packet_send(server,
3864 cmd->server->router->connection,
3865 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3866 packet->len, FALSE);
3871 /* Send to locally connected clients on the channel */
3872 silc_server_packet_send_local_channel(server, channel,
3873 SILC_PACKET_CHANNEL_KEY, 0,
3874 packet->data, packet->len, FALSE);
3876 silc_buffer_free(packet);
3880 silc_server_command_free(cmd);
3883 /* Server side of command USERS. Resolves clients and their USERS currently
3884 joined on the requested channel. The list of Client ID's and their modes
3885 on the channel is sent back. */
3887 SILC_SERVER_CMD_FUNC(users)
3889 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3890 SilcServer server = cmd->server;
3891 SilcChannelEntry channel;
3894 unsigned char *channel_id;
3895 unsigned int channel_id_len;
3896 SilcBuffer client_id_list;
3897 SilcBuffer client_mode_list;
3898 unsigned char lc[4];
3899 unsigned int list_count = 0;
3900 unsigned short ident = silc_command_get_ident(cmd->payload);
3902 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3904 /* Get Channel ID */
3905 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3908 SILC_STATUS_ERR_NO_CHANNEL_ID);
3911 id = silc_id_payload_parse_id(channel_id, channel_id_len);
3913 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3914 SILC_STATUS_ERR_NO_CHANNEL_ID);
3918 /* If we are server and we don't know about this channel we will send
3919 the command to our router. If we know about the channel then we also
3920 have the list of users already. */
3921 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3923 if (server->server_type == SILC_SERVER && !server->standalone &&
3927 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3928 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3930 /* Send USERS command */
3931 silc_server_packet_send(server, server->router->connection,
3932 SILC_PACKET_COMMAND, cmd->packet->flags,
3933 tmpbuf->data, tmpbuf->len, TRUE);
3935 /* Reprocess this packet after received reply */
3936 silc_server_command_pending(server, SILC_COMMAND_USERS,
3937 silc_command_get_ident(cmd->payload),
3938 silc_server_command_destructor,
3939 silc_server_command_users,
3940 silc_server_command_dup(cmd));
3941 cmd->pending = TRUE;
3942 silc_command_set_ident(cmd->payload, ident);
3944 silc_buffer_free(tmpbuf);
3949 /* We are router and we will check the global list as well. */
3950 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3952 /* Channel really does not exist */
3953 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3954 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3959 /* Get the users list */
3960 silc_server_get_users_on_channel(server, channel, &client_id_list,
3961 &client_mode_list, &list_count);
3964 SILC_PUT32_MSB(list_count, lc);
3967 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3968 SILC_STATUS_OK, ident, 4,
3969 2, channel_id, channel_id_len,
3971 4, client_id_list->data,
3972 client_id_list->len,
3973 5, client_mode_list->data,
3974 client_mode_list->len);
3975 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3976 packet->data, packet->len, FALSE);
3978 silc_buffer_free(packet);
3979 silc_buffer_free(client_id_list);
3980 silc_buffer_free(client_mode_list);
3984 silc_server_command_free(cmd);