5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
37 unsigned int arg_type,
39 unsigned int arg_len);
40 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
45 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
49 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
50 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
54 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(connect, CONNECT,
56 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
60 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
63 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
65 SILC_SERVER_CMD(restart, RESTART,
66 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
67 SILC_SERVER_CMD(close, CLOSE,
68 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
69 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
71 SILC_SERVER_CMD(silcoper, SILCOPER,
72 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
73 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
74 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
79 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
81 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
83 SILC_LOG_DEBUG(("Start")); \
86 silc_server_command_send_status_reply(cmd, command, \
87 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
88 silc_server_command_free(cmd); \
92 silc_server_command_send_status_reply(cmd, command, \
93 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
94 silc_server_command_free(cmd); \
99 /* Returns TRUE if the connection is registered. Unregistered connections
100 usually cannot send commands hence the check. */
102 static int silc_server_is_registered(SilcServer server,
103 SilcSocketConnection sock,
104 SilcServerCommandContext cmd,
107 SilcIDListData idata = (SilcIDListData)sock->user_data;
108 if (idata->registered)
111 silc_server_command_send_status_reply(cmd, command,
112 SILC_STATUS_ERR_NOT_REGISTERED);
113 silc_server_command_free(cmd);
117 /* Internal context to hold data when executed command with timeout. */
119 SilcServerCommandContext ctx;
120 SilcServerCommand *cmd;
121 } *SilcServerCommandTimeout;
123 /* Timeout callback to process commands with timeout for client. Client's
124 commands are always executed with timeout. */
126 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
128 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
129 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
131 /* Update access time */
132 client->last_command = time(NULL);
134 if (!(timeout->cmd->flags & SILC_CF_REG))
135 timeout->cmd->cb(timeout->ctx);
136 else if (silc_server_is_registered(timeout->ctx->server,
140 timeout->cmd->cb(timeout->ctx);
145 /* Processes received command packet. */
147 void silc_server_command_process(SilcServer server,
148 SilcSocketConnection sock,
149 SilcPacketContext *packet)
151 SilcServerCommandContext ctx;
152 SilcServerCommand *cmd;
155 /* Allocate command context. This must be free'd by the
156 command routine receiving it. */
157 ctx = silc_server_command_alloc();
158 ctx->server = server;
159 ctx->sock = silc_socket_dup(sock);
160 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
162 /* Parse the command payload in the packet */
163 ctx->payload = silc_command_payload_parse(packet->buffer);
165 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
166 silc_buffer_free(packet->buffer);
167 silc_packet_context_free(packet);
168 silc_socket_free(ctx->sock);
172 ctx->args = silc_command_get_args(ctx->payload);
174 /* Get the command */
175 command = silc_command_get(ctx->payload);
176 for (cmd = silc_command_list; cmd->cb; cmd++)
177 if (cmd->cmd == command)
181 silc_server_command_send_status_reply(ctx, command,
182 SILC_STATUS_ERR_UNKNOWN_COMMAND);
183 silc_server_command_free(ctx);
187 /* Execute client's commands always with timeout. Normally they are
188 executed with zero (0) timeout but if client is sending command more
189 frequently than once in 2 seconds, then the timeout may be 0 to 2
191 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
192 SilcClientEntry client = (SilcClientEntry)sock->user_data;
193 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
199 if (client->last_command && (time(NULL) - client->last_command) < 2) {
200 client->fast_command++;
203 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
204 client->fast_command--);
208 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
209 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
210 silc_task_register(server->timeout_queue, sock->sock,
211 silc_server_command_process_timeout,
213 2 - (time(NULL) - client->last_command), 0,
215 SILC_TASK_PRI_NORMAL);
217 silc_task_register(server->timeout_queue, sock->sock,
218 silc_server_command_process_timeout,
222 SILC_TASK_PRI_NORMAL);
226 /* Execute for server */
228 if (!(cmd->flags & SILC_CF_REG))
230 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
234 /* Allocate Command Context */
236 SilcServerCommandContext silc_server_command_alloc()
238 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
243 /* Free's the command context allocated before executing the command */
245 void silc_server_command_free(SilcServerCommandContext ctx)
248 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
250 if (ctx->users < 1) {
252 silc_command_free_payload(ctx->payload);
254 silc_packet_context_free(ctx->packet);
256 silc_socket_free(ctx->sock); /* Decrease reference counter */
261 /* Duplicate Command Context by adding reference counter. The context won't
262 be free'd untill it hits zero. */
264 SilcServerCommandContext
265 silc_server_command_dup(SilcServerCommandContext ctx)
268 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
273 /* Add new pending command to be executed when reply to a command has been
274 received. The `reply_cmd' is the command that will call the `callback'
275 with `context' when reply has been received. If `ident' is non-zero
276 the `callback' will be executed when received reply with command
277 identifier `ident'. */
279 void silc_server_command_pending(SilcServer server,
280 SilcCommand reply_cmd,
281 unsigned short ident,
282 SilcServerPendingDestructor destructor,
283 SilcCommandCb callback,
286 SilcServerCommandPending *reply;
288 reply = silc_calloc(1, sizeof(*reply));
289 reply->reply_cmd = reply_cmd;
290 reply->ident = ident;
291 reply->context = context;
292 reply->callback = callback;
293 reply->destructor = destructor;
294 silc_dlist_add(server->pending_commands, reply);
297 /* Deletes pending command by reply command type. */
299 void silc_server_command_pending_del(SilcServer server,
300 SilcCommand reply_cmd,
301 unsigned short ident)
303 SilcServerCommandPending *r;
305 silc_dlist_start(server->pending_commands);
306 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
307 if (r->reply_cmd == reply_cmd && r->ident == ident) {
308 silc_dlist_del(server->pending_commands, r);
314 /* Checks for pending commands and marks callbacks to be called from
315 the command reply function. Returns TRUE if there were pending command. */
317 int silc_server_command_pending_check(SilcServer server,
318 SilcServerCommandReplyContext ctx,
320 unsigned short ident)
322 SilcServerCommandPending *r;
324 silc_dlist_start(server->pending_commands);
325 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
326 if (r->reply_cmd == command && r->ident == ident) {
327 ctx->context = r->context;
328 ctx->callback = r->callback;
329 ctx->destructor = r->destructor;
338 /* Destructor function for pending callbacks. This is called when using
339 pending commands to free the context given for the pending command. */
341 static void silc_server_command_destructor(void *context)
343 silc_server_command_free((SilcServerCommandContext)context);
346 /* Sends simple status message as command reply packet */
349 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
351 SilcCommandStatus status)
355 SILC_LOG_DEBUG(("Sending command status %d", status));
358 silc_command_reply_payload_encode_va(command, status,
359 silc_command_get_ident(cmd->payload),
361 silc_server_packet_send(cmd->server, cmd->sock,
362 SILC_PACKET_COMMAND_REPLY, 0,
363 buffer->data, buffer->len, FALSE);
364 silc_buffer_free(buffer);
367 /* Sends command status reply with one extra argument. The argument
368 type must be sent as argument. */
371 silc_server_command_send_status_data(SilcServerCommandContext cmd,
373 SilcCommandStatus status,
374 unsigned int arg_type,
376 unsigned int arg_len)
380 SILC_LOG_DEBUG(("Sending command status %d", status));
383 silc_command_reply_payload_encode_va(command, status,
384 silc_command_get_ident(cmd->payload),
385 1, arg_type, arg, arg_len);
386 silc_server_packet_send(cmd->server, cmd->sock,
387 SILC_PACKET_COMMAND_REPLY, 0,
388 buffer->data, buffer->len, FALSE);
389 silc_buffer_free(buffer);
392 /******************************************************************************
396 ******************************************************************************/
399 silc_server_command_whois_parse(SilcServerCommandContext cmd,
400 SilcClientID ***client_id,
401 unsigned int *client_id_count,
409 unsigned int argc = silc_argument_get_arg_num(cmd->args);
412 /* If client ID is in the command it must be used instead of nickname */
413 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
415 /* No ID, get the nickname@server string and parse it. */
416 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
418 if (strchr(tmp, '@')) {
419 len = strcspn(tmp, "@");
420 *nickname = silc_calloc(len + 1, sizeof(char));
421 memcpy(*nickname, tmp, len);
422 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
423 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
425 *nickname = strdup(tmp);
428 silc_server_command_send_status_reply(cmd, command,
429 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
433 /* Command includes ID, we must use that. Also check whether the command
434 has more than one ID set - take them all. */
436 *client_id = silc_calloc(1, sizeof(**client_id));
437 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
438 if ((*client_id)[0] == NULL) {
439 silc_free(*client_id);
442 *client_id_count = 1;
444 /* Take all ID's from the command packet */
446 for (k = 1, i = 1; i < argc; i++) {
447 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
449 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
450 (*client_id_count + 1));
451 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
452 if ((*client_id)[k] == NULL) {
453 /* Cleanup all and fail */
454 for (i = 0; i < *client_id_count; i++)
455 silc_free((*client_id)[i]);
456 silc_free(*client_id);
459 (*client_id_count)++;
465 /* Command includes ID, use that */
468 /* Get the max count of reply messages allowed */
469 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
479 silc_server_command_whois_check(SilcServerCommandContext cmd,
480 SilcClientEntry *clients,
481 unsigned int clients_count)
483 SilcServer server = cmd->server;
485 SilcClientEntry entry;
487 for (i = 0; i < clients_count; i++) {
490 if (!entry->nickname || !entry->username || !entry->userinfo) {
492 unsigned short old_ident;
497 old_ident = silc_command_get_ident(cmd->payload);
498 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
499 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
501 /* Send WHOIS command */
502 silc_server_packet_send(server, entry->router->connection,
503 SILC_PACKET_COMMAND, cmd->packet->flags,
504 tmpbuf->data, tmpbuf->len, TRUE);
506 /* Reprocess this packet after received reply */
507 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
508 silc_command_get_ident(cmd->payload),
509 silc_server_command_destructor,
510 silc_server_command_whois,
511 silc_server_command_dup(cmd));
514 silc_command_set_ident(cmd->payload, old_ident);
516 silc_buffer_free(tmpbuf);
525 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
526 SilcClientEntry *clients,
527 unsigned int clients_count)
529 SilcServer server = cmd->server;
531 int i, count = 0, len;
532 SilcBuffer packet, idp;
533 SilcClientEntry entry;
534 SilcCommandStatus status;
535 unsigned short ident = silc_command_get_ident(cmd->payload);
536 char nh[128], uh[128];
537 unsigned char idle[4], mode[4];
538 SilcSocketConnection hsock;
540 status = SILC_STATUS_OK;
541 if (clients_count > 1)
542 status = SILC_STATUS_LIST_START;
544 for (i = 0; i < clients_count; i++) {
547 if (entry->connection && entry->data.registered == FALSE) {
548 if (clients_count == 1)
549 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
550 SILC_STATUS_ERR_NO_SUCH_NICK,
552 strlen(entry->nickname));
556 if (count && i - 1 == count)
559 if (clients_count > 2)
560 status = SILC_STATUS_LIST_ITEM;
562 if (clients_count > 1 && i == clients_count - 1)
563 status = SILC_STATUS_LIST_END;
565 /* Sanity check, however these should never fail. However, as
566 this sanity check has been added here they have failed. */
567 if (!entry->nickname || !entry->username || !entry->userinfo)
570 /* Send WHOIS reply */
571 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
572 tmp = silc_argument_get_first_arg(cmd->args, NULL);
574 memset(uh, 0, sizeof(uh));
575 memset(nh, 0, sizeof(nh));
576 memset(idle, 0, sizeof(idle));
578 strncat(nh, entry->nickname, strlen(entry->nickname));
579 if (!strchr(entry->nickname, '@')) {
581 len = entry->router ? strlen(entry->router->server_name) :
582 strlen(server->server_name);
583 strncat(nh, entry->router ? entry->router->server_name :
584 server->server_name, len);
587 strncat(uh, entry->username, strlen(entry->username));
588 if (!strchr(entry->username, '@')) {
590 hsock = (SilcSocketConnection)entry->connection;
591 len = strlen(hsock->hostname);
592 strncat(uh, hsock->hostname, len);
595 if (entry->connection) {
596 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
599 SILC_PUT32_MSB(entry->mode, mode);
601 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
603 2, idp->data, idp->len,
607 strlen(entry->userinfo),
611 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
612 0, packet->data, packet->len, FALSE);
614 silc_buffer_free(packet);
615 silc_buffer_free(idp);
620 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
622 SilcServer server = cmd->server;
623 char *nick = NULL, *server_name = NULL;
624 int count = 0, clients_count = 0;
625 SilcClientEntry *clients = NULL, entry;
626 SilcClientID **client_id = NULL;
627 unsigned int client_id_count = 0;
630 /* Protocol dictates that we must always send the received WHOIS request
631 to our router if we are normal server, so let's do it now unless we
632 are standalone. We will not send any replies to the client until we
633 have received reply from the router. */
634 if (server->server_type == SILC_SERVER && !cmd->pending &&
635 !server->standalone) {
637 unsigned short old_ident;
639 old_ident = silc_command_get_ident(cmd->payload);
640 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
641 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
643 /* Send WHOIS command to our router */
644 silc_server_packet_send(server, (SilcSocketConnection)
645 server->router->connection,
646 SILC_PACKET_COMMAND, cmd->packet->flags,
647 tmpbuf->data, tmpbuf->len, TRUE);
649 /* Reprocess this packet after received reply from router */
650 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
651 silc_command_get_ident(cmd->payload),
652 silc_server_command_destructor,
653 silc_server_command_whois,
654 silc_server_command_dup(cmd));
657 silc_command_set_ident(cmd->payload, old_ident);
659 silc_buffer_free(tmpbuf);
664 /* We are ready to process the command request. Let's search for the
665 requested client and send reply to the requesting client. */
667 /* Parse the whois request */
668 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
669 &nick, &server_name, &count,
673 /* Get all clients matching that ID or nickname from local list */
674 if (client_id_count) {
675 /* Check all Client ID's received in the command packet */
676 for (i = 0; i < client_id_count; i++) {
677 entry = silc_idlist_find_client_by_id(server->local_list,
680 clients = silc_realloc(clients, sizeof(*clients) *
681 (clients_count + 1));
682 clients[clients_count++] = entry;
686 clients = silc_idlist_get_clients_by_nickname(server->local_list,
690 clients = silc_idlist_get_clients_by_hash(server->local_list,
691 nick, server->md5hash,
695 /* Check global list as well */
697 if (client_id_count) {
698 /* Check all Client ID's received in the command packet */
699 for (i = 0; i < client_id_count; i++) {
700 entry = silc_idlist_find_client_by_id(server->global_list,
703 clients = silc_realloc(clients, sizeof(*clients) *
704 (clients_count + 1));
705 clients[clients_count++] = entry;
709 clients = silc_idlist_get_clients_by_nickname(server->global_list,
713 clients = silc_idlist_get_clients_by_hash(server->global_list,
714 nick, server->md5hash,
720 /* Such client(s) really does not exist in the SILC network. */
721 if (!client_id_count) {
722 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
723 SILC_STATUS_ERR_NO_SUCH_NICK,
724 3, nick, strlen(nick));
726 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
727 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
728 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
729 2, idp->data, idp->len);
730 silc_buffer_free(idp);
735 /* Router always finds the client entry if it exists in the SILC network.
736 However, it might be incomplete entry and does not include all the
737 mandatory fields that WHOIS command reply requires. Check for these and
738 make query from the server who owns the client if some fields are
740 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
745 /* Send the command reply to the client */
746 silc_server_command_whois_send_reply(cmd, clients, clients_count);
749 if (client_id_count) {
750 for (i = 0; i < client_id_count; i++)
751 silc_free(client_id[i]);
752 silc_free(client_id);
759 silc_free(server_name);
765 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
767 SilcServer server = cmd->server;
768 char *nick = NULL, *server_name = NULL;
769 int count = 0, clients_count = 0;
770 SilcClientEntry *clients = NULL, entry;
771 SilcClientID **client_id = NULL;
772 unsigned int client_id_count = 0;
775 /* Parse the whois request */
776 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
777 &nick, &server_name, &count,
781 /* Process the command request. Let's search for the requested client and
782 send reply to the requesting server. */
784 if (client_id_count) {
785 /* Check all Client ID's received in the command packet */
786 for (i = 0; i < client_id_count; i++) {
787 entry = silc_idlist_find_client_by_id(server->local_list,
790 clients = silc_realloc(clients, sizeof(*clients) *
791 (clients_count + 1));
792 clients[clients_count++] = entry;
796 clients = silc_idlist_get_clients_by_nickname(server->local_list,
800 clients = silc_idlist_get_clients_by_hash(server->local_list,
801 nick, server->md5hash,
805 /* If we are router we will check our global list as well. */
806 if (!clients && server->server_type == SILC_ROUTER) {
807 if (client_id_count) {
808 /* Check all Client ID's received in the command packet */
809 for (i = 0; i < client_id_count; i++) {
810 entry = silc_idlist_find_client_by_id(server->global_list,
813 clients = silc_realloc(clients, sizeof(*clients) *
814 (clients_count + 1));
815 clients[clients_count++] = entry;
819 clients = silc_idlist_get_clients_by_nickname(server->global_list,
823 clients = silc_idlist_get_clients_by_hash(server->global_list,
824 nick, server->md5hash,
830 /* Such a client really does not exist in the SILC network. */
831 if (!client_id_count) {
832 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
833 SILC_STATUS_ERR_NO_SUCH_NICK,
834 3, nick, strlen(nick));
836 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
837 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
838 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
839 2, idp->data, idp->len);
840 silc_buffer_free(idp);
845 /* Router always finds the client entry if it exists in the SILC network.
846 However, it might be incomplete entry and does not include all the
847 mandatory fields that WHOIS command reply requires. Check for these and
848 make query from the server who owns the client if some fields are
850 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
855 /* Send the command reply to the client */
856 silc_server_command_whois_send_reply(cmd, clients, clients_count);
859 if (client_id_count) {
860 for (i = 0; i < client_id_count; i++)
861 silc_free(client_id[i]);
862 silc_free(client_id);
869 silc_free(server_name);
874 /* Server side of command WHOIS. Processes user's query and sends found
875 results as command replies back to the client. */
877 SILC_SERVER_CMD_FUNC(whois)
879 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
882 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
884 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
885 ret = silc_server_command_whois_from_client(cmd);
886 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
887 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
888 ret = silc_server_command_whois_from_server(cmd);
891 silc_server_command_free(cmd);
894 /******************************************************************************
898 ******************************************************************************/
901 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
909 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
912 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
916 /* Get the nickname@server string and parse it. */
917 if (strchr(tmp, '@')) {
918 len = strcspn(tmp, "@");
919 *nickname = silc_calloc(len + 1, sizeof(char));
920 memcpy(*nickname, tmp, len);
921 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
922 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
924 *nickname = strdup(tmp);
926 /* Get the max count of reply messages allowed */
927 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
937 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
938 SilcClientEntry *clients,
939 unsigned int clients_count)
941 SilcServer server = cmd->server;
943 int i, count = 0, len;
944 SilcBuffer packet, idp;
945 SilcClientEntry entry = NULL;
946 SilcCommandStatus status;
947 unsigned short ident = silc_command_get_ident(cmd->payload);
950 status = SILC_STATUS_OK;
951 if (clients_count > 1)
952 status = SILC_STATUS_LIST_START;
954 for (i = 0; i < clients_count; i++) {
957 /* We will take only clients that are not valid anymore. They are the
958 ones that are not registered anymore but still have a ID. They
959 have disconnected us, and thus valid for WHOWAS. */
960 if (entry->data.registered == TRUE)
962 if (entry->id == NULL)
965 if (count && i - 1 == count)
970 if (clients_count > 2)
971 status = SILC_STATUS_LIST_ITEM;
973 if (clients_count > 1 && i == clients_count - 1)
974 status = SILC_STATUS_LIST_END;
976 /* Sanity check, however these should never fail. However, as
977 this sanity check has been added here they have failed. */
978 if (!entry->nickname || !entry->username)
981 /* Send WHOWAS reply */
982 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
983 tmp = silc_argument_get_first_arg(cmd->args, NULL);
986 char nh[256], uh[256];
988 memset(uh, 0, sizeof(uh));
989 memset(nh, 0, sizeof(nh));
991 strncat(nh, entry->nickname, strlen(entry->nickname));
992 if (!strchr(entry->nickname, '@')) {
994 len = entry->router ? strlen(entry->router->server_name) :
995 strlen(server->server_name);
996 strncat(nh, entry->router ? entry->router->server_name :
997 server->server_name, len);
1000 strncat(uh, entry->username, strlen(entry->username));
1001 if (!strchr(entry->username, '@')) {
1002 strncat(uh, "@", 1);
1003 strcat(uh, "*private*");
1007 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1009 2, idp->data, idp->len,
1013 strlen(entry->userinfo));
1016 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1017 0, packet->data, packet->len, FALSE);
1019 silc_buffer_free(packet);
1020 silc_buffer_free(idp);
1023 if (found == FALSE && entry)
1024 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1025 SILC_STATUS_ERR_NO_SUCH_NICK,
1027 strlen(entry->nickname));
1031 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1033 SilcServer server = cmd->server;
1034 char *nick = NULL, *server_name = NULL;
1035 int count = 0, clients_count = 0;
1036 SilcClientEntry *clients = NULL;
1039 /* Protocol dictates that we must always send the received WHOWAS request
1040 to our router if we are normal server, so let's do it now unless we
1041 are standalone. We will not send any replies to the client until we
1042 have received reply from the router. */
1043 if (server->server_type == SILC_SERVER &&
1044 !cmd->pending && !server->standalone) {
1046 unsigned short old_ident;
1048 old_ident = silc_command_get_ident(cmd->payload);
1049 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1050 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1052 /* Send WHOWAS command to our router */
1053 silc_server_packet_send(server, (SilcSocketConnection)
1054 server->router->connection,
1055 SILC_PACKET_COMMAND, cmd->packet->flags,
1056 tmpbuf->data, tmpbuf->len, TRUE);
1058 /* Reprocess this packet after received reply from router */
1059 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1060 silc_command_get_ident(cmd->payload),
1061 silc_server_command_destructor,
1062 silc_server_command_whois,
1063 silc_server_command_dup(cmd));
1064 cmd->pending = TRUE;
1066 silc_command_set_ident(cmd->payload, old_ident);
1068 silc_buffer_free(tmpbuf);
1073 /* We are ready to process the command request. Let's search for the
1074 requested client and send reply to the requesting client. */
1076 /* Parse the whowas request */
1077 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1080 /* Get all clients matching that nickname from local list */
1081 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1085 clients = silc_idlist_get_clients_by_hash(server->local_list,
1086 nick, server->md5hash,
1089 /* Check global list as well */
1091 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1095 clients = silc_idlist_get_clients_by_hash(server->global_list,
1096 nick, server->md5hash,
1101 /* Such client(s) really does not exist in the SILC network. */
1102 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1103 SILC_STATUS_ERR_NO_SUCH_NICK,
1104 3, nick, strlen(nick));
1108 /* Send the command reply to the client */
1109 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1117 silc_free(server_name);
1123 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1125 SilcServer server = cmd->server;
1126 char *nick = NULL, *server_name = NULL;
1127 int count = 0, clients_count = 0;
1128 SilcClientEntry *clients = NULL;
1131 /* Parse the whowas request */
1132 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1135 /* Process the command request. Let's search for the requested client and
1136 send reply to the requesting server. */
1138 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1142 clients = silc_idlist_get_clients_by_hash(server->local_list,
1143 nick, server->md5hash,
1146 /* If we are router we will check our global list as well. */
1147 if (!clients && server->server_type == SILC_ROUTER) {
1148 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1152 clients = silc_idlist_get_clients_by_hash(server->global_list,
1153 nick, server->md5hash,
1158 /* Such a client really does not exist in the SILC network. */
1159 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1160 SILC_STATUS_ERR_NO_SUCH_NICK,
1161 3, nick, strlen(nick));
1165 /* Send the command reply to the client */
1166 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1174 silc_free(server_name);
1179 /* Server side of command WHOWAS. */
1181 SILC_SERVER_CMD_FUNC(whowas)
1183 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1186 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1188 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1189 ret = silc_server_command_whowas_from_client(cmd);
1190 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1191 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1192 ret = silc_server_command_whowas_from_server(cmd);
1195 silc_server_command_free(cmd);
1198 /******************************************************************************
1202 ******************************************************************************/
1204 /* Checks that all mandatory fields are present. If not then send WHOIS
1205 request to the server who owns the client. We use WHOIS because we want
1206 to get as much information as possible at once. */
1209 silc_server_command_identify_check(SilcServerCommandContext cmd,
1210 SilcClientEntry *clients,
1211 unsigned int clients_count)
1213 SilcServer server = cmd->server;
1215 SilcClientEntry entry;
1217 for (i = 0; i < clients_count; i++) {
1220 if (!entry->nickname) {
1222 unsigned short old_ident;
1227 old_ident = silc_command_get_ident(cmd->payload);
1228 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1229 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1230 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1232 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1233 now anyway so make it a good one. */
1234 silc_server_packet_send(server, entry->router->connection,
1235 SILC_PACKET_COMMAND, cmd->packet->flags,
1236 tmpbuf->data, tmpbuf->len, TRUE);
1238 /* Reprocess this packet after received reply */
1239 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1240 silc_command_get_ident(cmd->payload),
1241 silc_server_command_destructor,
1242 silc_server_command_identify,
1243 silc_server_command_dup(cmd));
1245 cmd->pending = TRUE;
1247 /* Put old data back to the Command Payload we just changed */
1248 silc_command_set_ident(cmd->payload, old_ident);
1249 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1251 silc_buffer_free(tmpbuf);
1260 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1261 SilcClientEntry *clients,
1262 unsigned int clients_count)
1264 SilcServer server = cmd->server;
1266 int i, count = 0, len;
1267 SilcBuffer packet, idp;
1268 SilcClientEntry entry;
1269 SilcCommandStatus status;
1270 unsigned short ident = silc_command_get_ident(cmd->payload);
1272 status = SILC_STATUS_OK;
1273 if (clients_count > 1)
1274 status = SILC_STATUS_LIST_START;
1276 for (i = 0; i < clients_count; i++) {
1279 if (entry->connection && entry->data.registered == FALSE) {
1280 if (clients_count == 1)
1281 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1282 SILC_STATUS_ERR_NO_SUCH_NICK,
1284 strlen(entry->nickname));
1288 if (count && i - 1 == count)
1291 if (clients_count > 2)
1292 status = SILC_STATUS_LIST_ITEM;
1294 if (clients_count > 1 && i == clients_count - 1)
1295 status = SILC_STATUS_LIST_END;
1297 /* Send IDENTIFY reply */
1298 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1299 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1303 char nh[256], uh[256];
1304 SilcSocketConnection hsock;
1306 memset(uh, 0, sizeof(uh));
1307 memset(nh, 0, sizeof(nh));
1309 strncat(nh, entry->nickname, strlen(entry->nickname));
1310 if (!strchr(entry->nickname, '@')) {
1311 strncat(nh, "@", 1);
1312 len = entry->router ? strlen(entry->router->server_name) :
1313 strlen(server->server_name);
1314 strncat(nh, entry->router ? entry->router->server_name :
1315 server->server_name, len);
1318 if (!entry->username) {
1319 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1321 2, idp->data, idp->len,
1324 strncat(uh, entry->username, strlen(entry->username));
1325 if (!strchr(entry->username, '@')) {
1326 strncat(uh, "@", 1);
1327 hsock = (SilcSocketConnection)entry->connection;
1328 len = strlen(hsock->hostname);
1329 strncat(uh, hsock->hostname, len);
1332 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1334 2, idp->data, idp->len,
1339 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1340 0, packet->data, packet->len, FALSE);
1342 silc_buffer_free(packet);
1343 silc_buffer_free(idp);
1349 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1351 SilcServer server = cmd->server;
1352 char *nick = NULL, *server_name = NULL;
1353 int count = 0, clients_count = 0;
1354 SilcClientEntry *clients = NULL, entry;
1355 SilcClientID **client_id = NULL;
1356 unsigned int client_id_count = 0;
1359 /* Protocol dictates that we must always send the received IDENTIFY request
1360 to our router if we are normal server, so let's do it now unless we
1361 are standalone. We will not send any replies to the client until we
1362 have received reply from the router. */
1363 if (server->server_type == SILC_SERVER &&
1364 !cmd->pending && !server->standalone) {
1366 unsigned short old_ident;
1368 old_ident = silc_command_get_ident(cmd->payload);
1369 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1370 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1372 /* Send IDENTIFY command to our router */
1373 silc_server_packet_send(server, (SilcSocketConnection)
1374 server->router->connection,
1375 SILC_PACKET_COMMAND, cmd->packet->flags,
1376 tmpbuf->data, tmpbuf->len, TRUE);
1378 /* Reprocess this packet after received reply from router */
1379 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1380 silc_command_get_ident(cmd->payload),
1381 silc_server_command_destructor,
1382 silc_server_command_identify,
1383 silc_server_command_dup(cmd));
1384 cmd->pending = TRUE;
1386 silc_command_set_ident(cmd->payload, old_ident);
1388 silc_buffer_free(tmpbuf);
1393 /* We are ready to process the command request. Let's search for the
1394 requested client and send reply to the requesting client. */
1396 /* Parse the IDENTIFY request */
1397 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1398 &nick, &server_name, &count,
1399 SILC_COMMAND_IDENTIFY))
1402 /* Get all clients matching that ID or nickname from local list */
1403 if (client_id_count) {
1404 /* Check all Client ID's received in the command packet */
1405 for (i = 0; i < client_id_count; i++) {
1406 entry = silc_idlist_find_client_by_id(server->local_list,
1407 client_id[i], NULL);
1409 clients = silc_realloc(clients, sizeof(*clients) *
1410 (clients_count + 1));
1411 clients[clients_count++] = entry;
1415 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1419 clients = silc_idlist_get_clients_by_hash(server->local_list,
1420 nick, server->md5hash,
1424 /* Check global list as well */
1426 if (client_id_count) {
1427 /* Check all Client ID's received in the command packet */
1428 for (i = 0; i < client_id_count; i++) {
1429 entry = silc_idlist_find_client_by_id(server->global_list,
1430 client_id[i], NULL);
1432 clients = silc_realloc(clients, sizeof(*clients) *
1433 (clients_count + 1));
1434 clients[clients_count++] = entry;
1438 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1442 clients = silc_idlist_get_clients_by_hash(server->global_list,
1443 nick, server->md5hash,
1449 /* Such a client really does not exist in the SILC network. */
1450 if (!client_id_count) {
1451 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1452 SILC_STATUS_ERR_NO_SUCH_NICK,
1453 3, nick, strlen(nick));
1455 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1456 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1457 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1458 2, idp->data, idp->len);
1459 silc_buffer_free(idp);
1464 /* Check that all mandatory fields are present and request those data
1465 from the server who owns the client if necessary. */
1466 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1471 /* Send the command reply to the client */
1472 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1475 if (client_id_count) {
1476 for (i = 0; i < client_id_count; i++)
1477 silc_free(client_id[i]);
1478 silc_free(client_id);
1485 silc_free(server_name);
1491 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1493 SilcServer server = cmd->server;
1494 char *nick = NULL, *server_name = NULL;
1495 int count = 0, clients_count = 0;
1496 SilcClientEntry *clients = NULL, entry;
1497 SilcClientID **client_id = NULL;
1498 unsigned int client_id_count = 0;
1501 /* Parse the IDENTIFY request */
1502 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1503 &nick, &server_name, &count,
1504 SILC_COMMAND_IDENTIFY))
1507 /* Process the command request. Let's search for the requested client and
1508 send reply to the requesting server. */
1510 if (client_id_count) {
1511 /* Check all Client ID's received in the command packet */
1512 for (i = 0; i < client_id_count; i++) {
1513 entry = silc_idlist_find_client_by_id(server->local_list,
1514 client_id[i], NULL);
1516 clients = silc_realloc(clients, sizeof(*clients) *
1517 (clients_count + 1));
1518 clients[clients_count++] = entry;
1522 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1526 clients = silc_idlist_get_clients_by_hash(server->local_list,
1527 nick, server->md5hash,
1531 /* If we are router we will check our global list as well. */
1532 if (!clients && server->server_type == SILC_ROUTER) {
1533 if (client_id_count) {
1534 /* Check all Client ID's received in the command packet */
1535 for (i = 0; i < client_id_count; i++) {
1536 entry = silc_idlist_find_client_by_id(server->global_list,
1537 client_id[i], NULL);
1539 clients = silc_realloc(clients, sizeof(*clients) *
1540 (clients_count + 1));
1541 clients[clients_count++] = entry;
1545 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1549 clients = silc_idlist_get_clients_by_hash(server->global_list,
1550 nick, server->md5hash,
1556 /* Such a client really does not exist in the SILC network. */
1557 if (!client_id_count) {
1558 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1559 SILC_STATUS_ERR_NO_SUCH_NICK,
1560 3, nick, strlen(nick));
1562 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1563 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1564 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1565 2, idp->data, idp->len);
1566 silc_buffer_free(idp);
1571 /* Check that all mandatory fields are present and request those data
1572 from the server who owns the client if necessary. */
1573 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1578 /* Send the command reply */
1579 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1582 if (client_id_count) {
1583 for (i = 0; i < client_id_count; i++)
1584 silc_free(client_id[i]);
1585 silc_free(client_id);
1592 silc_free(server_name);
1597 SILC_SERVER_CMD_FUNC(identify)
1599 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1602 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1604 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1605 ret = silc_server_command_identify_from_client(cmd);
1606 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1607 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1608 ret = silc_server_command_identify_from_server(cmd);
1611 silc_server_command_free(cmd);
1614 /* Checks string for bad characters and returns TRUE if they are found. */
1616 static int silc_server_command_bad_chars(char *nick)
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;
1624 if (strchr(nick, '/')) return TRUE;
1625 if (strchr(nick, '@')) return TRUE;
1630 /* Server side of command NICK. Sets nickname for user. Setting
1631 nickname causes generation of a new client ID for the client. The
1632 new client ID is sent to the client after changing the nickname. */
1634 SILC_SERVER_CMD_FUNC(nick)
1636 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1637 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1638 SilcServer server = cmd->server;
1639 SilcBuffer packet, nidp, oidp;
1640 SilcClientID *new_id;
1642 unsigned short ident = silc_command_get_ident(cmd->payload);
1644 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1647 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1649 /* Check nickname */
1650 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1651 if (silc_server_command_bad_chars(nick) == TRUE) {
1652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1653 SILC_STATUS_ERR_BAD_NICKNAME);
1657 if (strlen(nick) > 128)
1660 /* Create new Client ID */
1661 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1662 cmd->server->md5hash, nick,
1665 /* Send notify about nickname change to our router. We send the new
1666 ID and ask to replace it with the old one. If we are router the
1667 packet is broadcasted. Send NICK_CHANGE notify. */
1668 if (!server->standalone)
1669 silc_server_send_notify_nick_change(server, server->router->connection,
1670 server->server_type == SILC_SERVER ?
1671 FALSE : TRUE, client->id,
1672 new_id, SILC_ID_CLIENT_LEN);
1674 /* Remove old cache entry */
1675 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1678 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1682 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1683 silc_free(client->id);
1686 /* Save the nickname as this client is our local client */
1687 if (client->nickname)
1688 silc_free(client->nickname);
1690 client->nickname = strdup(nick);
1691 client->id = new_id;
1693 /* Update client cache */
1694 silc_idcache_add(server->local_list->clients, client->nickname,
1695 SILC_ID_CLIENT, client->id, (void *)client, TRUE, FALSE);
1697 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1699 /* Send NICK_CHANGE notify to the client's channels */
1700 silc_server_send_notify_on_channels(server, NULL, client,
1701 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1702 oidp->data, oidp->len,
1703 nidp->data, nidp->len);
1705 /* Send the new Client ID as reply command back to client */
1706 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1707 SILC_STATUS_OK, ident, 1,
1708 2, nidp->data, nidp->len);
1709 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1710 0, packet->data, packet->len, FALSE);
1712 silc_buffer_free(packet);
1713 silc_buffer_free(nidp);
1714 silc_buffer_free(oidp);
1717 silc_server_command_free(cmd);
1720 SILC_SERVER_CMD_FUNC(list)
1724 /* Server side of TOPIC command. Sets topic for channel and/or returns
1725 current topic to client. */
1727 SILC_SERVER_CMD_FUNC(topic)
1729 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1730 SilcServer server = cmd->server;
1731 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1732 SilcChannelID *channel_id;
1733 SilcChannelEntry channel;
1734 SilcChannelClientEntry chl;
1735 SilcBuffer packet, idp;
1737 unsigned int argc, tmp_len;
1738 unsigned short ident = silc_command_get_ident(cmd->payload);
1740 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1742 argc = silc_argument_get_arg_num(cmd->args);
1744 /* Get Channel ID */
1745 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1748 SILC_STATUS_ERR_NO_CHANNEL_ID);
1751 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1754 SILC_STATUS_ERR_NO_CHANNEL_ID);
1758 /* Check whether the channel exists */
1759 channel = silc_idlist_find_channel_by_id(server->local_list,
1762 channel = silc_idlist_find_channel_by_id(server->global_list,
1765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1766 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1773 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1776 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1780 if (strlen(tmp) > 256) {
1781 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1782 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1786 /* See whether has rights to change topic */
1787 silc_list_start(channel->user_list);
1788 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1789 if (chl->client == client)
1792 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1793 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1794 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1795 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1800 /* Set the topic for channel */
1802 silc_free(channel->topic);
1803 channel->topic = strdup(tmp);
1805 /* Send TOPIC_SET notify type to the network */
1806 if (!server->standalone)
1807 silc_server_send_notify_topic_set(server, server->router->connection,
1808 server->server_type == SILC_ROUTER ?
1809 TRUE : FALSE, channel, client->id,
1810 SILC_ID_CLIENT_LEN, channel->topic);
1812 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1814 /* Send notify about topic change to all clients on the channel */
1815 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1816 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1817 idp->data, idp->len,
1818 channel->topic, strlen(channel->topic));
1819 silc_buffer_free(idp);
1822 /* Send the topic to client as reply packet */
1823 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1825 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1826 SILC_STATUS_OK, ident, 2,
1827 2, idp->data, idp->len,
1829 strlen(channel->topic));
1831 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1832 SILC_STATUS_OK, ident, 1,
1833 2, idp->data, idp->len);
1834 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1835 0, packet->data, packet->len, FALSE);
1837 silc_buffer_free(packet);
1838 silc_buffer_free(idp);
1839 silc_free(channel_id);
1842 silc_server_command_free(cmd);
1845 /* Server side of INVITE command. Invites some client to join some channel. */
1847 SILC_SERVER_CMD_FUNC(invite)
1849 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1850 SilcServer server = cmd->server;
1851 SilcSocketConnection sock = cmd->sock, dest_sock;
1852 SilcClientEntry sender, dest;
1853 SilcClientID *dest_id;
1854 SilcChannelEntry channel;
1855 SilcChannelID *channel_id;
1860 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1862 /* Get destination ID */
1863 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1865 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1866 SILC_STATUS_ERR_NO_CLIENT_ID);
1869 dest_id = silc_id_payload_parse_id(tmp, len);
1871 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1872 SILC_STATUS_ERR_NO_CLIENT_ID);
1876 /* Get Channel ID */
1877 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1879 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1880 SILC_STATUS_ERR_NO_CHANNEL_ID);
1883 channel_id = silc_id_payload_parse_id(tmp, len);
1885 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1886 SILC_STATUS_ERR_NO_CHANNEL_ID);
1890 /* Check whether the channel exists */
1891 channel = silc_idlist_find_channel_by_id(server->local_list,
1894 channel = silc_idlist_find_channel_by_id(server->global_list,
1897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1898 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1903 /* Check whether the sender of this command is on the channel. */
1904 sender = (SilcClientEntry)sock->user_data;
1905 if (!silc_server_client_on_channel(sender, channel)) {
1906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1907 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1911 /* Check whether the channel is invite-only channel. If yes then the
1912 sender of this command must be at least channel operator. */
1913 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1914 SilcChannelClientEntry chl;
1916 silc_list_start(channel->user_list);
1917 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1918 if (chl->client == sender) {
1919 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1920 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1921 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1928 /* Find the connection data for the destination. If it is local we will
1929 send it directly otherwise we will send it to router for routing. */
1930 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1932 dest_sock = (SilcSocketConnection)dest->connection;
1934 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1936 /* Check whether the requested client is already on the channel. */
1937 /* XXX if we are normal server we don't know about global clients on
1938 the channel thus we must request it (USERS command), check from
1939 local cache as well. */
1940 if (silc_server_client_on_channel(dest, channel)) {
1941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1942 SILC_STATUS_ERR_USER_ON_CHANNEL);
1946 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1948 /* Send notify to the client that is invited to the channel */
1949 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1951 SILC_NOTIFY_TYPE_INVITE, 2,
1952 sidp->data, sidp->len, tmp, len);
1954 /* Send command reply */
1955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1958 silc_buffer_free(sidp);
1961 silc_server_command_free(cmd);
1966 SilcSocketConnection sock;
1970 /* Quits connection to client. This gets called if client won't
1971 close the connection even when it has issued QUIT command. */
1973 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1975 QuitInternal q = (QuitInternal)context;
1977 /* Free all client specific data, such as client entry and entires
1978 on channels this client may be on. */
1979 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1981 q->sock->user_data = NULL;
1983 /* Close the connection on our side */
1984 silc_server_close_connection(q->server, q->sock);
1986 silc_free(q->signoff);
1990 /* Quits SILC session. This is the normal way to disconnect client. */
1992 SILC_SERVER_CMD_FUNC(quit)
1994 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1995 SilcServer server = cmd->server;
1996 SilcSocketConnection sock = cmd->sock;
1998 unsigned char *tmp = NULL;
1999 unsigned int len = 0;
2001 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2003 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2006 /* Get destination ID */
2007 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2011 q = silc_calloc(1, sizeof(*q));
2014 q->signoff = tmp ? strdup(tmp) : NULL;
2016 /* We quit the connection with little timeout */
2017 silc_task_register(server->timeout_queue, sock->sock,
2018 silc_server_command_quit_cb, (void *)q,
2019 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2022 silc_server_command_free(cmd);
2025 /* Server side of command KILL. This command is used by router operator
2026 to remove an client from the SILC Network temporarily. */
2028 SILC_SERVER_CMD_FUNC(kill)
2030 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2031 SilcServer server = cmd->server;
2032 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2033 SilcClientEntry remote_client;
2034 SilcClientID *client_id;
2035 unsigned char *tmp, *comment;
2036 unsigned int tmp_len, tmp_len2;
2038 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2040 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2043 /* KILL command works only on router */
2044 if (server->server_type != SILC_ROUTER) {
2045 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2046 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2050 /* Check whether client has the permissions. */
2051 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2053 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2057 /* Get the client ID */
2058 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2060 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2061 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2064 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2066 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2067 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2071 /* Get the client entry */
2072 remote_client = silc_idlist_find_client_by_id(server->local_list,
2074 if (!remote_client) {
2075 remote_client = silc_idlist_find_client_by_id(server->global_list,
2077 if (!remote_client) {
2078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2079 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2085 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2089 /* Send reply to the sender */
2090 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2093 /* Send the KILL notify packets. First send it to the channel, then
2094 to our primary router and then directly to the client who is being
2095 killed right now. */
2097 /* Send KILLED notify to the channels. It is not sent to the client
2098 as it will be sent differently destined directly to the client and not
2100 silc_server_send_notify_on_channels(server, remote_client,
2101 remote_client, SILC_NOTIFY_TYPE_KILLED,
2104 comment, comment ? tmp_len2 : 0);
2106 /* Send KILLED notify to primary route */
2107 if (!server->standalone)
2108 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2109 remote_client->id, SILC_ID_CLIENT_LEN,
2112 /* Send KILLED notify to the client directly */
2113 silc_server_send_notify_killed(server, remote_client->connection ?
2114 remote_client->connection :
2115 remote_client->router->connection, FALSE,
2116 remote_client->id, SILC_ID_CLIENT_LEN,
2119 /* Remove the client from all channels. This generates new keys to the
2120 channels as well. */
2121 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2124 /* Remove the client entry, If it is locally connected then we will also
2125 disconnect the client here */
2126 if (remote_client->data.registered && remote_client->connection) {
2127 /* Remove locally conneted client */
2128 SilcSocketConnection sock = remote_client->connection;
2129 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2130 silc_server_close_connection(server, sock);
2132 /* Remove remote client */
2133 if (!silc_idlist_del_client(server->global_list, remote_client))
2134 silc_idlist_del_client(server->local_list, remote_client);
2138 silc_server_command_free(cmd);
2141 /* Server side of command INFO. This sends information about us to
2142 the client. If client requested specific server we will send the
2143 command to that server. */
2145 SILC_SERVER_CMD_FUNC(info)
2147 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2148 SilcServer server = cmd->server;
2149 SilcBuffer packet, idp;
2150 char info_string[256], *dest_server;
2152 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
2154 /* Get server name */
2155 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2157 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2158 SILC_STATUS_ERR_NO_SUCH_SERVER);
2162 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2163 /* Send our reply */
2164 memset(info_string, 0, sizeof(info_string));
2165 snprintf(info_string, sizeof(info_string),
2166 "location: %s server: %s admin: %s <%s>",
2167 server->config->admin_info->location,
2168 server->config->admin_info->server_type,
2169 server->config->admin_info->admin_name,
2170 server->config->admin_info->admin_email);
2172 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2174 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2175 SILC_STATUS_OK, 0, 2,
2176 2, idp->data, idp->len,
2178 strlen(info_string));
2179 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2180 packet->data, packet->len, FALSE);
2182 silc_buffer_free(packet);
2183 silc_buffer_free(idp);
2185 /* Send this command to the requested server */
2187 if (server->server_type == SILC_SERVER && !server->standalone) {
2191 if (server->server_type == SILC_ROUTER) {
2197 silc_server_command_free(cmd);
2200 /* Server side of command PING. This just replies to the ping. */
2202 SILC_SERVER_CMD_FUNC(ping)
2204 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2205 SilcServer server = cmd->server;
2210 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2213 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2215 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2216 SILC_STATUS_ERR_NO_SERVER_ID);
2219 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2223 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2224 /* Send our reply */
2225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2228 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2229 SILC_STATUS_ERR_NO_SUCH_SERVER);
2236 silc_server_command_free(cmd);
2239 /* Internal routine to join channel. The channel sent to this function
2240 has been either created or resolved from ID lists. This joins the sent
2241 client to the channel. */
2243 static void silc_server_command_join_channel(SilcServer server,
2244 SilcServerCommandContext cmd,
2245 SilcChannelEntry channel,
2246 SilcClientID *client_id,
2250 SilcSocketConnection sock = cmd->sock;
2252 unsigned int tmp_len, user_count;
2253 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2254 SilcClientEntry client;
2255 SilcChannelClientEntry chl;
2256 SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
2257 unsigned short ident = silc_command_get_ident(cmd->payload);
2259 SILC_LOG_DEBUG(("Start"));
2264 /* Get passphrase */
2265 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2267 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2268 memcpy(passphrase, tmp, tmp_len);
2272 * Check channel modes
2275 /* Check invite list if channel is invite-only channel */
2276 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2277 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2278 /* Invite list is specified. Check whether client is invited in the
2279 list. If not, then check whether it has been invited otherwise. */
2282 /* XXX client must be invited to be able to join the channel */
2286 /* Check ban list if set */
2287 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2291 /* Check the channel passphrase if set. */
2292 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2293 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
2294 strlen(channel->mode_data.passphrase))) {
2295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2296 SILC_STATUS_ERR_BAD_PASSWORD);
2301 /* Check user count limit if set. */
2302 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2303 if (silc_list_count(channel->user_list) + 1 >
2304 channel->mode_data.user_limit) {
2305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2306 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2312 * Client is allowed to join to the channel. Make it happen.
2315 /* Get the client entry */
2316 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2317 client = (SilcClientEntry)sock->user_data;
2319 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2322 /* XXX actually this is useless since router finds always cell's
2323 local clients from its local lists. */
2324 client = silc_idlist_find_client_by_id(server->global_list, client_id,
2331 /* Check whether the client already is on the channel */
2332 if (silc_server_client_on_channel(client, channel)) {
2333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2334 SILC_STATUS_ERR_USER_ON_CHANNEL);
2338 /* Generate new channel key as protocol dictates */
2339 if ((!created && silc_list_count(channel->user_list) > 0) ||
2340 !channel->channel_key)
2341 silc_server_create_channel_key(server, channel, 0);
2343 /* Send the channel key. This is broadcasted to the channel but is not
2344 sent to the client who is joining to the channel. */
2345 silc_server_send_channel_key(server, NULL, channel,
2346 server->server_type == SILC_ROUTER ?
2347 FALSE : !server->standalone);
2349 /* Join the client to the channel by adding it to channel's user list.
2350 Add also the channel to client entry's channels list for fast cross-
2352 chl = silc_calloc(1, sizeof(*chl));
2354 chl->client = client;
2355 chl->channel = channel;
2356 silc_list_add(channel->user_list, chl);
2357 silc_list_add(client->channels, chl);
2359 /* Get users on the channel */
2360 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2363 /* Encode Client ID Payload of the original client who wants to join */
2364 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2366 /* Encode command reply packet */
2367 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2368 SILC_PUT32_MSB(channel->mode, mode);
2369 SILC_PUT32_MSB(created, tmp2);
2370 SILC_PUT32_MSB(user_count, tmp3);
2371 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2372 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2373 strlen(channel->channel_key->
2375 channel->channel_key->cipher->name,
2376 channel->key_len / 8, channel->key);
2378 if (!channel->topic) {
2380 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2381 SILC_STATUS_OK, ident, 9,
2382 2, channel->channel_name,
2383 strlen(channel->channel_name),
2384 3, chidp->data, chidp->len,
2385 4, clidp->data, clidp->len,
2388 7, keyp->data, keyp->len,
2390 13, user_list->data, user_list->len,
2391 14, mode_list->data,
2395 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2396 SILC_STATUS_OK, ident, 10,
2397 2, channel->channel_name,
2398 strlen(channel->channel_name),
2399 3, chidp->data, chidp->len,
2400 4, clidp->data, clidp->len,
2403 7, keyp->data, keyp->len,
2405 strlen(channel->topic),
2407 13, user_list->data, user_list->len,
2408 14, mode_list->data,
2412 /* Send command reply */
2413 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2414 reply->data, reply->len, FALSE);
2416 if (!cmd->pending) {
2417 /* Send JOIN notify to locally connected clients on the channel */
2418 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2419 SILC_NOTIFY_TYPE_JOIN, 2,
2420 clidp->data, clidp->len,
2421 chidp->data, chidp->len);
2423 /* Send JOIN notify packet to our primary router */
2424 if (!server->standalone)
2425 silc_server_send_notify_join(server, server->router->connection,
2426 server->server_type == SILC_ROUTER ?
2427 TRUE : FALSE, channel, client->id,
2428 SILC_ID_CLIENT_LEN);
2431 silc_buffer_free(reply);
2432 silc_buffer_free(clidp);
2433 silc_buffer_free(chidp);
2434 silc_buffer_free(keyp);
2435 silc_buffer_free(user_list);
2436 silc_buffer_free(mode_list);
2440 silc_free(passphrase);
2443 /* Server side of command JOIN. Joins client into requested channel. If
2444 the channel does not exist it will be created. */
2446 SILC_SERVER_CMD_FUNC(join)
2448 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2449 SilcServer server = cmd->server;
2451 char *tmp, *channel_name = NULL, *cipher, *hmac;
2452 SilcChannelEntry channel;
2453 unsigned int umode = 0;
2454 int created = FALSE;
2455 SilcClientID *client_id;
2457 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2459 /* Get channel name */
2460 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2462 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2463 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2468 if (strlen(channel_name) > 256)
2469 channel_name[255] = '\0';
2471 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2472 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2473 SILC_STATUS_ERR_BAD_CHANNEL);
2474 silc_free(channel_name);
2478 /* Get Client ID of the client who is joining to the channel */
2479 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2481 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2482 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2485 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2488 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2492 /* Get cipher and hmac name */
2493 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2494 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2496 /* See if the channel exists */
2497 channel = silc_idlist_find_channel_by_name(server->local_list,
2498 channel_name, NULL);
2500 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2501 /* If this is coming from client the Client ID in the command packet must
2502 be same as the client's ID. */
2503 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2504 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2505 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2506 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2507 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2513 /* Channel not found */
2515 /* If we are standalone server we don't have a router, we just create
2516 the channel by ourselves. */
2517 if (server->standalone) {
2518 channel = silc_server_create_new_channel(server, server->id, cipher,
2519 hmac, channel_name, TRUE);
2520 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2525 /* The channel does not exist on our server. If we are normal server
2526 we will send JOIN command to our router which will handle the
2527 joining procedure (either creates the channel if it doesn't exist
2528 or joins the client to it). */
2529 if (server->server_type == SILC_SERVER) {
2531 unsigned short old_ident;
2533 old_ident = silc_command_get_ident(cmd->payload);
2534 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2535 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2537 /* Send JOIN command to our router */
2538 silc_server_packet_send(server, (SilcSocketConnection)
2539 server->router->connection,
2540 SILC_PACKET_COMMAND, cmd->packet->flags,
2541 tmpbuf->data, tmpbuf->len, TRUE);
2543 /* Reprocess this packet after received reply from router */
2544 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2545 silc_command_get_ident(cmd->payload),
2546 silc_server_command_destructor,
2547 silc_server_command_join,
2548 silc_server_command_dup(cmd));
2549 cmd->pending = TRUE;
2553 /* We are router and the channel does not seem exist so we will check
2554 our global list as well for the channel. */
2555 channel = silc_idlist_find_channel_by_name(server->global_list,
2556 channel_name, NULL);
2558 /* Channel really does not exist, create it */
2559 channel = silc_server_create_new_channel(server, server->id, cipher,
2560 hmac, channel_name, TRUE);
2561 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2568 /* Channel not found */
2570 /* If the command came from router and/or we are normal server then
2571 something went wrong with the joining as the channel was not found.
2572 We can't do anything else but ignore this. */
2573 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2574 server->server_type == SILC_SERVER)
2577 /* We are router and the channel does not seem exist so we will check
2578 our global list as well for the channel. */
2579 channel = silc_idlist_find_channel_by_name(server->global_list,
2580 channel_name, NULL);
2582 /* Channel really does not exist, create it */
2583 channel = silc_server_create_new_channel(server, server->id, cipher,
2584 hmac, channel_name, TRUE);
2585 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2591 /* If the channel does not have global users and is also empty it means the
2592 channel was created globally (by our router) and the client will be the
2593 channel founder and operator. */
2594 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2595 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2596 created = TRUE; /* Created globally by our router */
2599 /* Join to the channel */
2600 silc_server_command_join_channel(server, cmd, channel, client_id,
2603 silc_free(client_id);
2606 silc_server_command_free(cmd);
2609 /* Server side of command MOTD. Sends server's current "message of the
2610 day" to the client. */
2612 SILC_SERVER_CMD_FUNC(motd)
2614 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2615 SilcServer server = cmd->server;
2619 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2621 /* XXX show currently only our motd */
2623 if (server->config && server->config->motd &&
2624 server->config->motd->motd_file) {
2627 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2632 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2638 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2643 silc_server_command_free(cmd);
2646 /* Server side of command UMODE. Client can use this command to set/unset
2647 user mode. Client actually cannot set itself to be as server/router
2648 operator so this can be used only to unset the modes. */
2650 SILC_SERVER_CMD_FUNC(umode)
2652 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2653 SilcServer server = cmd->server;
2654 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2656 unsigned char *tmp_mask;
2658 unsigned short ident = silc_command_get_ident(cmd->payload);
2660 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2663 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
2665 /* Get the client's mode mask */
2666 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2669 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2672 SILC_GET32_MSB(mask, tmp_mask);
2678 if (mask & SILC_UMODE_SERVER_OPERATOR) {
2679 /* Cannot operator mode */
2680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2681 SILC_STATUS_ERR_PERM_DENIED);
2684 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
2685 /* Remove the server operator rights */
2686 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
2689 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
2690 /* Cannot operator mode */
2691 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2692 SILC_STATUS_ERR_PERM_DENIED);
2695 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
2696 /* Remove the router operator rights */
2697 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
2700 /* Send command reply to sender */
2701 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
2702 SILC_STATUS_OK, ident, 1,
2704 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2705 packet->data, packet->len, FALSE);
2706 silc_buffer_free(packet);
2709 silc_server_command_free(cmd);
2712 /* Checks that client has rights to add or remove channel modes. If any
2713 of the checks fails FALSE is returned. */
2715 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2716 SilcChannelClientEntry client,
2719 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2720 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2722 /* Check whether has rights to change anything */
2723 if (!is_op && !is_fo)
2726 /* Check whether has rights to change everything */
2730 /* We know that client is channel operator, check that they are not
2731 changing anything that requires channel founder rights. Rest of the
2732 modes are available automatically for channel operator. */
2734 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2735 if (is_op && !is_fo)
2738 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2739 if (is_op && !is_fo)
2744 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2745 if (is_op && !is_fo)
2748 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2749 if (is_op && !is_fo)
2754 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2755 if (is_op && !is_fo)
2758 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2759 if (is_op && !is_fo)
2767 /* Server side command of CMODE. Changes channel mode */
2769 SILC_SERVER_CMD_FUNC(cmode)
2771 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2772 SilcServer server = cmd->server;
2773 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2774 SilcChannelID *channel_id;
2775 SilcChannelEntry channel;
2776 SilcChannelClientEntry chl;
2777 SilcBuffer packet, cidp;
2778 unsigned char *tmp, *tmp_id, *tmp_mask;
2779 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2780 unsigned short ident = silc_command_get_ident(cmd->payload);
2782 SILC_LOG_DEBUG(("Start"));
2784 argc = silc_argument_get_arg_num(cmd->args);
2786 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2787 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2791 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2792 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2796 /* Get Channel ID */
2797 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2799 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2800 SILC_STATUS_ERR_NO_CHANNEL_ID);
2803 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2806 SILC_STATUS_ERR_NO_CHANNEL_ID);
2810 /* Get the channel mode mask */
2811 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2814 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2817 SILC_GET32_MSB(mode_mask, tmp_mask);
2819 /* Get channel entry */
2820 channel = silc_idlist_find_channel_by_id(server->local_list,
2823 channel = silc_idlist_find_channel_by_id(server->global_list,
2826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2827 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2832 /* Check whether this client is on the channel */
2833 if (!silc_server_client_on_channel(client, channel)) {
2834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2835 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2839 /* Get entry to the channel user list */
2840 silc_list_start(channel->user_list);
2841 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2842 if (chl->client == client)
2845 /* Check that client has rights to change any requested channel modes */
2846 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2847 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2848 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2853 * Check the modes. Modes that requires nothing special operation are
2857 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2858 /* Channel uses private keys to protect traffic. Client(s) has set the
2859 key locally they want to use, server does not know that key. */
2860 /* Nothing interesting to do here now */
2862 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2863 /* The mode is removed and we need to generate and distribute
2864 new channel key. Clients are not using private channel keys
2865 anymore after this. */
2867 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2870 /* Re-generate channel key */
2871 silc_server_create_channel_key(server, channel, 0);
2873 /* Encode channel key payload to be distributed on the channel */
2875 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2876 strlen(channel->channel_key->
2878 channel->channel_key->cipher->name,
2879 channel->key_len / 8, channel->key);
2881 /* If we are normal server then we will send it to our router. If we
2882 are router we will send it to all local servers that has clients on
2884 if (server->server_type == SILC_SERVER) {
2885 if (!server->standalone)
2886 silc_server_packet_send(server,
2887 cmd->server->router->connection,
2888 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2894 /* Send to locally connected clients on the channel */
2895 silc_server_packet_send_local_channel(server, channel,
2896 SILC_PACKET_CHANNEL_KEY, 0,
2897 packet->data, packet->len, FALSE);
2898 silc_buffer_free(packet);
2902 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2903 /* User limit is set on channel */
2904 unsigned int user_limit;
2906 /* Get user limit */
2907 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2909 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2910 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2911 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2915 SILC_GET32_MSB(user_limit, tmp);
2916 channel->mode_data.user_limit = user_limit;
2919 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2920 /* User limit mode is unset. Remove user limit */
2921 channel->mode_data.user_limit = 0;
2924 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2925 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2926 /* Passphrase has been set to channel */
2928 /* Get the passphrase */
2929 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2931 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2932 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2936 /* Save the passphrase */
2937 channel->mode_data.passphrase = strdup(tmp);
2940 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2941 /* Passphrase mode is unset. remove the passphrase */
2942 if (channel->mode_data.passphrase) {
2943 silc_free(channel->mode_data.passphrase);
2944 channel->mode_data.passphrase = NULL;
2949 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2950 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2951 /* Ban list is specified for channel */
2954 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2956 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2957 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2961 /* XXX check that channel founder is not banned */
2963 /* Save the ban list */
2964 channel->mode_data.ban_list = strdup(tmp);
2967 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2968 /* Ban mode is unset. Remove the entire ban list */
2969 if (channel->mode_data.ban_list) {
2970 silc_free(channel->mode_data.ban_list);
2971 channel->mode_data.ban_list = NULL;
2976 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2977 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2978 /* Invite list is specified for channel */
2980 /* Get invite list */
2981 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2984 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2988 /* Save the invite linst */
2989 channel->mode_data.invite_list = strdup(tmp);
2992 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2993 /* Invite list mode is unset. Remove the entire invite list */
2994 if (channel->mode_data.invite_list) {
2995 silc_free(channel->mode_data.invite_list);
2996 channel->mode_data.invite_list = NULL;
3001 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3002 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3003 /* Cipher to use protect the traffic */
3004 unsigned int key_len;
3007 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
3009 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3010 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3014 /* XXX Duplicated code, make own function for this!! */
3016 /* Delete old cipher and allocate the new one */
3017 silc_cipher_free(channel->channel_key);
3018 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
3019 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3020 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3023 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
3025 /* Re-generate channel key */
3026 silc_server_create_channel_key(server, channel, key_len);
3028 /* Encode channel key payload to be distributed on the channel */
3030 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3031 strlen(channel->channel_key->
3033 channel->channel_key->cipher->name,
3034 channel->key_len / 8, channel->key);
3036 /* If we are normal server then we will send it to our router. If we
3037 are router we will send it to all local servers that has clients on
3039 if (server->server_type == SILC_SERVER) {
3040 if (!server->standalone)
3041 silc_server_packet_send(server,
3042 cmd->server->router->connection,
3043 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3049 /* Send to locally connected clients on the channel */
3050 silc_server_packet_send_local_channel(server, channel,
3051 SILC_PACKET_CHANNEL_KEY, 0,
3052 packet->data, packet->len, FALSE);
3053 silc_buffer_free(packet);
3056 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3057 /* Cipher mode is unset. Remove the cipher and revert back to
3060 if (channel->mode_data.cipher) {
3061 silc_free(channel->mode_data.cipher);
3062 channel->mode_data.cipher = NULL;
3063 channel->mode_data.key_len = 0;
3066 /* Generate new cipher and key for the channel */
3068 /* XXX Duplicated code, make own function for this!! */
3070 /* Delete old cipher and allocate default one */
3071 silc_cipher_free(channel->channel_key);
3072 if (!channel->cipher)
3073 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
3075 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
3076 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3077 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3082 /* Re-generate channel key */
3083 silc_server_create_channel_key(server, channel, 0);
3085 /* Encode channel key payload to be distributed on the channel */
3087 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3088 strlen(channel->channel_key->
3090 channel->channel_key->cipher->name,
3091 channel->key_len / 8, channel->key);
3093 /* If we are normal server then we will send it to our router. If we
3094 are router we will send it to all local servers that has clients on
3096 if (server->server_type == SILC_SERVER) {
3097 if (!server->standalone)
3098 silc_server_packet_send(server,
3099 cmd->server->router->connection,
3100 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3106 /* Send to locally connected clients on the channel */
3107 silc_server_packet_send_local_channel(server, channel,
3108 SILC_PACKET_CHANNEL_KEY, 0,
3109 packet->data, packet->len, FALSE);
3110 silc_buffer_free(packet);
3114 /* Finally, set the mode */
3115 channel->mode = mode_mask;
3117 /* Send CMODE_CHANGE notify */
3118 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3119 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3120 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
3121 cidp->data, cidp->len,
3124 /* Set CMODE notify type to network */
3125 if (!server->standalone)
3126 silc_server_send_notify_cmode(server, server->router->connection,
3127 server->server_type == SILC_ROUTER ?
3128 TRUE : FALSE, channel,
3129 mode_mask, client->id, SILC_ID_CLIENT_LEN);
3131 /* Send command reply to sender */
3132 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3133 SILC_STATUS_OK, ident, 1,
3135 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3136 packet->data, packet->len, FALSE);
3138 silc_buffer_free(packet);
3139 silc_free(channel_id);
3143 silc_server_command_free(cmd);
3146 /* Server side of CUMODE command. Changes client's mode on a channel. */
3148 SILC_SERVER_CMD_FUNC(cumode)
3150 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3151 SilcServer server = cmd->server;
3152 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3153 SilcChannelID *channel_id;
3154 SilcClientID *client_id;
3155 SilcChannelEntry channel;
3156 SilcClientEntry target_client;
3157 SilcChannelClientEntry chl;
3158 SilcBuffer packet, idp;
3159 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3160 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3162 unsigned short ident = silc_command_get_ident(cmd->payload);
3164 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3166 /* Get Channel ID */
3167 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3169 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3170 SILC_STATUS_ERR_NO_CHANNEL_ID);
3173 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3175 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3176 SILC_STATUS_ERR_NO_CHANNEL_ID);
3180 /* Get channel entry */
3181 channel = silc_idlist_find_channel_by_id(server->local_list,
3184 channel = silc_idlist_find_channel_by_id(server->global_list,
3187 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3188 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3193 /* Check whether sender is on the channel */
3194 if (!silc_server_client_on_channel(client, channel)) {
3195 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3196 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3200 /* Check that client has rights to change other's rights */
3201 silc_list_start(channel->user_list);
3202 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3203 if (chl->client == client) {
3204 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3205 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3206 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3207 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3211 sender_mask = chl->mode;
3216 /* Get the target client's channel mode mask */
3217 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3219 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3220 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3223 SILC_GET32_MSB(target_mask, tmp_mask);
3225 /* Get target Client ID */
3226 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3228 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3229 SILC_STATUS_ERR_NO_CLIENT_ID);
3232 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3234 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3235 SILC_STATUS_ERR_NO_CLIENT_ID);
3239 /* Get target client's entry */
3240 target_client = silc_idlist_find_client_by_id(server->local_list,
3242 if (!target_client) {
3243 target_client = silc_idlist_find_client_by_id(server->global_list,
3247 /* Check whether target client is on the channel */
3248 if (!silc_server_client_on_channel(target_client, channel)) {
3249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3250 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3254 /* Get entry to the channel user list */
3255 silc_list_start(channel->user_list);
3256 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3257 if (chl->client == target_client)
3264 /* If the target client is founder, no one else can change their mode
3266 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3268 SILC_STATUS_ERR_NOT_YOU);
3272 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3273 /* Cannot promote anyone to channel founder */
3274 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3275 SILC_STATUS_ERR_NOT_YOU);
3278 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3279 if (target_client == client) {
3280 /* Remove channel founder rights from itself */
3281 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3285 SILC_STATUS_ERR_NOT_YOU);
3291 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3292 /* Promote to operator */
3293 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3294 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3298 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3299 /* Demote to normal user */
3300 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3305 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3307 /* Send notify to channel, notify only if mode was actually changed. */
3309 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3310 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3311 idp->data, idp->len,
3315 /* Set CUMODE notify type to network */
3316 if (!server->standalone)
3317 silc_server_send_notify_cumode(server, server->router->connection,
3318 server->server_type == SILC_ROUTER ?
3319 TRUE : FALSE, channel,
3320 target_mask, client->id,
3323 SILC_ID_CLIENT_LEN);
3326 /* Send command reply to sender */
3327 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3328 SILC_STATUS_OK, ident, 2,
3330 3, tmp_id, tmp_len);
3331 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3332 packet->data, packet->len, FALSE);
3334 silc_buffer_free(packet);
3335 silc_free(channel_id);
3336 silc_free(client_id);
3337 silc_buffer_free(idp);
3340 silc_server_command_free(cmd);
3343 /* Server side of KICK command. Kicks client out of channel. */
3345 SILC_SERVER_CMD_FUNC(kick)
3347 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3348 SilcServer server = cmd->server;
3349 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3350 SilcClientEntry target_client;
3351 SilcChannelID *channel_id;
3352 SilcClientID *client_id;
3353 SilcChannelEntry channel;
3354 SilcChannelClientEntry chl;
3356 unsigned int tmp_len;
3357 unsigned char *tmp, *comment;
3359 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3361 /* Get Channel ID */
3362 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3364 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3365 SILC_STATUS_ERR_NO_CHANNEL_ID);
3368 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3371 SILC_STATUS_ERR_NO_CHANNEL_ID);
3375 /* Get channel entry */
3376 channel = silc_idlist_find_channel_by_id(server->local_list,
3379 channel = silc_idlist_find_channel_by_id(server->local_list,
3382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3383 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3388 /* Check whether sender is on the channel */
3389 if (!silc_server_client_on_channel(client, channel)) {
3390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3391 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3395 /* Check that the kicker is channel operator or channel founder */
3396 silc_list_start(channel->user_list);
3397 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3398 if (chl->client == client) {
3399 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3400 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3401 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3408 /* Get target Client ID */
3409 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3411 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3412 SILC_STATUS_ERR_NO_CLIENT_ID);
3415 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3418 SILC_STATUS_ERR_NO_CLIENT_ID);
3422 /* Get target client's entry */
3423 target_client = silc_idlist_find_client_by_id(server->local_list,
3425 if (!target_client) {
3426 target_client = silc_idlist_find_client_by_id(server->global_list,
3430 /* Check that the target client is not channel founder. Channel founder
3431 cannot be kicked from the channel. */
3432 silc_list_start(channel->user_list);
3433 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3434 if (chl->client == target_client) {
3435 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3437 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3444 /* Check whether target client is on the channel */
3445 if (!silc_server_client_on_channel(target_client, channel)) {
3446 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3447 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3453 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3457 /* Send command reply to sender */
3458 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3461 /* Send KICKED notify to local clients on the channel */
3462 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3463 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3464 SILC_NOTIFY_TYPE_KICKED,
3466 idp->data, idp->len,
3467 comment, comment ? strlen(comment) : 0);
3468 silc_buffer_free(idp);
3470 /* Remove the client from the channel. If the channel does not exist
3471 after removing the client then the client kicked itself off the channel
3472 and we don't have to send anything after that. */
3473 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3474 target_client, FALSE))
3477 /* Send KICKED notify to primary route */
3478 if (!server->standalone)
3479 silc_server_send_notify_kicked(server, server->router->connection,
3480 server->server_type == SILC_ROUTER ?
3481 TRUE : FALSE, channel,
3482 target_client->id, SILC_ID_CLIENT_LEN,
3485 /* Re-generate channel key */
3486 silc_server_create_channel_key(server, channel, 0);
3488 /* Send the channel key to the channel. The key of course is not sent
3489 to the client who was kicked off the channel. */
3490 silc_server_send_channel_key(server, target_client->connection, channel,
3491 server->server_type == SILC_ROUTER ?
3492 FALSE : !server->standalone);
3495 silc_server_command_free(cmd);
3498 /* Server side of OPER command. Client uses this comand to obtain server
3499 operator privileges to this server/router. */
3501 SILC_SERVER_CMD_FUNC(oper)
3503 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3504 SilcServer server = cmd->server;
3505 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3506 unsigned char *username, *auth;
3507 unsigned int tmp_len;
3508 SilcServerConfigSectionAdminConnection *admin;
3509 SilcIDListData idata = (SilcIDListData)client;
3511 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
3513 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3516 /* Get the username */
3517 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3520 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3524 /* Get the admin configuration */
3525 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3526 username, client->nickname);
3528 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3529 username, client->nickname);
3531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3532 SILC_STATUS_ERR_AUTH_FAILED);
3537 /* Get the authentication payload */
3538 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3541 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3545 /* Verify the authentication data */
3546 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3547 admin->auth_data, admin->auth_data_len,
3548 idata->hash, client->id, SILC_ID_CLIENT)) {
3549 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3550 SILC_STATUS_ERR_AUTH_FAILED);
3554 /* Client is now server operator */
3555 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3557 /* Send reply to the sender */
3558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3562 silc_server_command_free(cmd);
3565 /* Server side of SILCOPER command. Client uses this comand to obtain router
3566 operator privileges to this router. */
3568 SILC_SERVER_CMD_FUNC(silcoper)
3570 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3571 SilcServer server = cmd->server;
3572 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3573 unsigned char *username, *auth;
3574 unsigned int tmp_len;
3575 SilcServerConfigSectionAdminConnection *admin;
3576 SilcIDListData idata = (SilcIDListData)client;
3578 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
3580 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3583 /* Get the username */
3584 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3586 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3587 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3591 /* Get the admin configuration */
3592 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3593 username, client->nickname);
3595 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3596 username, client->nickname);
3598 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3599 SILC_STATUS_ERR_AUTH_FAILED);
3604 /* Get the authentication payload */
3605 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3608 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3612 /* Verify the authentication data */
3613 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3614 admin->auth_data, admin->auth_data_len,
3615 idata->hash, client->id, SILC_ID_CLIENT)) {
3616 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3617 SILC_STATUS_ERR_AUTH_FAILED);
3621 /* Client is now router operator */
3622 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
3624 /* Send reply to the sender */
3625 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3629 silc_server_command_free(cmd);
3632 /* Server side command of CONNECT. Connects us to the specified remote
3633 server or router. */
3635 SILC_SERVER_CMD_FUNC(connect)
3637 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3638 SilcServer server = cmd->server;
3639 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3640 unsigned char *tmp, *host;
3641 unsigned int tmp_len;
3642 unsigned int port = SILC_PORT;
3644 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
3646 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3649 /* Check whether client has the permissions. */
3650 if (client->mode == SILC_UMODE_NONE) {
3651 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3652 SILC_STATUS_ERR_NO_SERVER_PRIV);
3656 if (server->server_type == SILC_ROUTER &&
3657 client->mode & SILC_UMODE_SERVER_OPERATOR) {
3658 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3659 SILC_STATUS_ERR_NO_ROUTER_PRIV);
3663 /* Get the remote server */
3664 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3666 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3667 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3672 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3674 SILC_GET32_MSB(port, tmp);
3677 /* Create the connection. It is done with timeout and is async. */
3678 silc_server_create_connection(server, host, port);
3680 /* Send reply to the sender */
3681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3685 silc_server_command_free(cmd);
3688 SILC_SERVER_CMD_FUNC(restart)
3692 /* Server side command of CLOSE. Closes connection to a specified server. */
3694 SILC_SERVER_CMD_FUNC(close)
3696 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3697 SilcServer server = cmd->server;
3698 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3699 SilcServerEntry server_entry;
3700 SilcSocketConnection sock;
3702 unsigned int tmp_len;
3703 unsigned char *name;
3704 unsigned int port = SILC_PORT;
3706 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3708 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3711 /* Check whether client has the permissions. */
3712 if (client->mode == SILC_UMODE_NONE) {
3713 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3714 SILC_STATUS_ERR_NO_SERVER_PRIV);
3718 /* Get the remote server */
3719 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3721 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3722 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3727 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3729 SILC_GET32_MSB(port, tmp);
3732 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3734 if (!server_entry) {
3735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3736 SILC_STATUS_ERR_NO_SERVER_ID);
3740 /* Send reply to the sender */
3741 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3744 /* Close the connection to the server */
3745 sock = (SilcSocketConnection)server_entry->connection;
3746 silc_server_free_sock_user_data(server, sock);
3747 silc_server_close_connection(server, sock);
3750 silc_server_command_free(cmd);
3753 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3754 active connections. */
3756 SILC_SERVER_CMD_FUNC(shutdown)
3758 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3759 SilcServer server = cmd->server;
3760 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3762 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3764 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3767 /* Check whether client has the permission. */
3768 if (client->mode == SILC_UMODE_NONE) {
3769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3770 SILC_STATUS_ERR_NO_SERVER_PRIV);
3774 /* Send reply to the sender */
3775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3778 /* Then, gracefully, or not, bring the server down. */
3779 silc_server_stop(server);
3783 silc_server_command_free(cmd);
3786 /* Server side command of LEAVE. Removes client from a channel. */
3788 SILC_SERVER_CMD_FUNC(leave)
3790 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3791 SilcServer server = cmd->server;
3792 SilcSocketConnection sock = cmd->sock;
3793 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3795 SilcChannelEntry channel;
3797 unsigned int i, len;
3800 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3802 /* Get Channel ID */
3803 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3806 SILC_STATUS_ERR_NO_CHANNEL_ID);
3809 id = silc_id_payload_parse_id(tmp, len);
3811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3812 SILC_STATUS_ERR_NO_CHANNEL_ID);
3816 /* Get channel entry */
3817 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3819 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3822 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3827 /* Check whether this client is on the channel */
3828 if (!silc_server_client_on_channel(id_entry, channel)) {
3829 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3830 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3834 /* Notify routers that they should remove this client from their list
3835 of clients on the channel. Send LEAVE notify type. */
3836 if (!server->standalone)
3837 silc_server_send_notify_leave(server, server->router->connection,
3838 server->server_type == SILC_ROUTER ?
3839 TRUE : FALSE, channel, id_entry->id,
3840 SILC_ID_CLIENT_LEN);
3842 /* Remove client from channel */
3843 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3845 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3848 /* If the channel does not exist anymore we won't send anything */
3852 /* Re-generate channel key */
3853 silc_server_create_channel_key(server, channel, 0);
3855 /* Encode channel key payload to be distributed on the channel */
3857 silc_channel_key_payload_encode(len, tmp,
3858 strlen(channel->channel_key->cipher->name),
3859 channel->channel_key->cipher->name,
3860 channel->key_len / 8, channel->key);
3862 /* If we are normal server then we will send it to our router. If we
3863 are router we will send it to all local servers that has clients on
3865 if (server->server_type == SILC_SERVER) {
3866 if (!server->standalone)
3867 silc_server_packet_send(server,
3868 cmd->server->router->connection,
3869 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3870 packet->len, FALSE);
3875 /* Send to locally connected clients on the channel */
3876 silc_server_packet_send_local_channel(server, channel,
3877 SILC_PACKET_CHANNEL_KEY, 0,
3878 packet->data, packet->len, FALSE);
3880 silc_buffer_free(packet);
3884 silc_server_command_free(cmd);
3887 /* Server side of command USERS. Resolves clients and their USERS currently
3888 joined on the requested channel. The list of Client ID's and their modes
3889 on the channel is sent back. */
3891 SILC_SERVER_CMD_FUNC(users)
3893 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3894 SilcServer server = cmd->server;
3895 SilcChannelEntry channel;
3898 unsigned char *channel_id;
3899 unsigned int channel_id_len;
3900 SilcBuffer client_id_list;
3901 SilcBuffer client_mode_list;
3902 unsigned char lc[4];
3903 unsigned int list_count = 0;
3904 unsigned short ident = silc_command_get_ident(cmd->payload);
3906 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3908 /* Get Channel ID */
3909 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3912 SILC_STATUS_ERR_NO_CHANNEL_ID);
3915 id = silc_id_payload_parse_id(channel_id, channel_id_len);
3917 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3918 SILC_STATUS_ERR_NO_CHANNEL_ID);
3922 /* If we are server and we don't know about this channel we will send
3923 the command to our router. If we know about the channel then we also
3924 have the list of users already. */
3925 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3927 if (server->server_type == SILC_SERVER && !server->standalone &&
3931 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3932 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3934 /* Send USERS command */
3935 silc_server_packet_send(server, server->router->connection,
3936 SILC_PACKET_COMMAND, cmd->packet->flags,
3937 tmpbuf->data, tmpbuf->len, TRUE);
3939 /* Reprocess this packet after received reply */
3940 silc_server_command_pending(server, SILC_COMMAND_USERS,
3941 silc_command_get_ident(cmd->payload),
3942 silc_server_command_destructor,
3943 silc_server_command_users,
3944 silc_server_command_dup(cmd));
3945 cmd->pending = TRUE;
3946 silc_command_set_ident(cmd->payload, ident);
3948 silc_buffer_free(tmpbuf);
3953 /* We are router and we will check the global list as well. */
3954 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3956 /* Channel really does not exist */
3957 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3958 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3963 /* Get the users list */
3964 silc_server_get_users_on_channel(server, channel, &client_id_list,
3965 &client_mode_list, &list_count);
3968 SILC_PUT32_MSB(list_count, lc);
3971 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3972 SILC_STATUS_OK, ident, 4,
3973 2, channel_id, channel_id_len,
3975 4, client_id_list->data,
3976 client_id_list->len,
3977 5, client_mode_list->data,
3978 client_mode_list->len);
3979 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3980 packet->data, packet->len, FALSE);
3982 silc_buffer_free(packet);
3983 silc_buffer_free(client_id_list);
3984 silc_buffer_free(client_mode_list);
3988 silc_server_command_free(cmd);