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;
154 /* Allocate command context. This must be free'd by the
155 command routine receiving it. */
156 ctx = silc_server_command_alloc();
157 ctx->server = server;
158 ctx->sock = silc_socket_dup(sock);
159 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
161 /* Parse the command payload in the packet */
162 ctx->payload = silc_command_payload_parse(packet->buffer);
164 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
165 silc_buffer_free(packet->buffer);
166 silc_packet_context_free(packet);
167 silc_socket_free(ctx->sock);
171 ctx->args = silc_command_get_args(ctx->payload);
173 /* Get the command */
174 for (cmd = silc_command_list; cmd->cb; cmd++)
175 if (cmd->cmd == silc_command_get(ctx->payload))
179 SILC_LOG_ERROR(("Unknown command, packet dropped"));
180 silc_server_command_free(ctx);
184 /* Execute client's commands always with timeout. Normally they are
185 executed with zero (0) timeout but if client is sending command more
186 frequently than once in 2 seconds, then the timeout may be 0 to 2
188 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
189 SilcClientEntry client = (SilcClientEntry)sock->user_data;
190 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
196 if (client->last_command && (time(NULL) - client->last_command) < 2) {
197 client->fast_command++;
200 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
201 client->fast_command--);
205 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
206 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
207 silc_task_register(server->timeout_queue, sock->sock,
208 silc_server_command_process_timeout,
210 2 - (time(NULL) - client->last_command), 0,
212 SILC_TASK_PRI_NORMAL);
214 silc_task_register(server->timeout_queue, sock->sock,
215 silc_server_command_process_timeout,
219 SILC_TASK_PRI_NORMAL);
223 /* Execute for server */
225 if (!(cmd->flags & SILC_CF_REG))
227 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
231 /* Allocate Command Context */
233 SilcServerCommandContext silc_server_command_alloc()
235 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
240 /* Free's the command context allocated before executing the command */
242 void silc_server_command_free(SilcServerCommandContext ctx)
245 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
247 if (ctx->users < 1) {
249 silc_command_free_payload(ctx->payload);
251 silc_packet_context_free(ctx->packet);
253 silc_socket_free(ctx->sock); /* Decrease reference counter */
258 /* Duplicate Command Context by adding reference counter. The context won't
259 be free'd untill it hits zero. */
261 SilcServerCommandContext
262 silc_server_command_dup(SilcServerCommandContext ctx)
265 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
270 /* Add new pending command to be executed when reply to a command has been
271 received. The `reply_cmd' is the command that will call the `callback'
272 with `context' when reply has been received. If `ident' is non-zero
273 the `callback' will be executed when received reply with command
274 identifier `ident'. */
276 void silc_server_command_pending(SilcServer server,
277 SilcCommand reply_cmd,
278 unsigned short ident,
279 SilcServerPendingDestructor destructor,
280 SilcCommandCb callback,
283 SilcServerCommandPending *reply;
285 reply = silc_calloc(1, sizeof(*reply));
286 reply->reply_cmd = reply_cmd;
287 reply->ident = ident;
288 reply->context = context;
289 reply->callback = callback;
290 reply->destructor = destructor;
291 silc_dlist_add(server->pending_commands, reply);
294 /* Deletes pending command by reply command type. */
296 void silc_server_command_pending_del(SilcServer server,
297 SilcCommand reply_cmd,
298 unsigned short ident)
300 SilcServerCommandPending *r;
302 silc_dlist_start(server->pending_commands);
303 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
304 if (r->reply_cmd == reply_cmd && r->ident == ident) {
305 silc_dlist_del(server->pending_commands, r);
311 /* Checks for pending commands and marks callbacks to be called from
312 the command reply function. Returns TRUE if there were pending command. */
314 int silc_server_command_pending_check(SilcServer server,
315 SilcServerCommandReplyContext ctx,
317 unsigned short ident)
319 SilcServerCommandPending *r;
321 silc_dlist_start(server->pending_commands);
322 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
323 if (r->reply_cmd == command && r->ident == ident) {
324 ctx->context = r->context;
325 ctx->callback = r->callback;
326 ctx->destructor = r->destructor;
335 /* Destructor function for pending callbacks. This is called when using
336 pending commands to free the context given for the pending command. */
338 static void silc_server_command_destructor(void *context)
340 silc_server_command_free((SilcServerCommandContext)context);
343 /* Sends simple status message as command reply packet */
346 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
348 SilcCommandStatus status)
352 SILC_LOG_DEBUG(("Sending command status %d", status));
354 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
355 silc_server_packet_send(cmd->server, cmd->sock,
356 SILC_PACKET_COMMAND_REPLY, 0,
357 buffer->data, buffer->len, FALSE);
358 silc_buffer_free(buffer);
361 /* Sends command status reply with one extra argument. The argument
362 type must be sent as argument. */
365 silc_server_command_send_status_data(SilcServerCommandContext cmd,
367 SilcCommandStatus status,
368 unsigned int arg_type,
370 unsigned int arg_len)
374 SILC_LOG_DEBUG(("Sending command status %d", status));
376 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
377 arg_type, arg, arg_len);
378 silc_server_packet_send(cmd->server, cmd->sock,
379 SILC_PACKET_COMMAND_REPLY, 0,
380 buffer->data, buffer->len, FALSE);
381 silc_buffer_free(buffer);
384 /******************************************************************************
388 ******************************************************************************/
391 silc_server_command_whois_parse(SilcServerCommandContext cmd,
392 SilcClientID ***client_id,
393 unsigned int *client_id_count,
401 unsigned int argc = silc_argument_get_arg_num(cmd->args);
404 /* If client ID is in the command it must be used instead of nickname */
405 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
407 /* No ID, get the nickname@server string and parse it. */
408 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
410 if (strchr(tmp, '@')) {
411 len = strcspn(tmp, "@");
412 *nickname = silc_calloc(len + 1, sizeof(char));
413 memcpy(*nickname, tmp, len);
414 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
415 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
417 *nickname = strdup(tmp);
420 silc_server_command_send_status_reply(cmd, command,
421 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
425 /* Command includes ID, we must use that. Also check whether the command
426 has more than one ID set - take them all. */
428 *client_id = silc_calloc(1, sizeof(**client_id));
429 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
430 if ((*client_id)[0] == NULL) {
431 silc_free(*client_id);
434 *client_id_count = 1;
436 /* Take all ID's from the command packet */
438 for (k = 1, i = 1; i < argc; i++) {
439 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
441 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
442 (*client_id_count + 1));
443 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
444 if ((*client_id)[k] == NULL) {
445 /* Cleanup all and fail */
446 for (i = 0; i < *client_id_count; i++)
447 silc_free((*client_id)[i]);
448 silc_free(*client_id);
451 (*client_id_count)++;
457 /* Command includes ID, use that */
460 /* Get the max count of reply messages allowed */
461 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
471 silc_server_command_whois_check(SilcServerCommandContext cmd,
472 SilcClientEntry *clients,
473 unsigned int clients_count)
475 SilcServer server = cmd->server;
477 SilcClientEntry entry;
479 for (i = 0; i < clients_count; i++) {
482 if (!entry->nickname || !entry->username) {
484 unsigned short old_ident;
489 old_ident = silc_command_get_ident(cmd->payload);
490 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
491 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
493 /* Send WHOIS command */
494 silc_server_packet_send(server, entry->router->connection,
495 SILC_PACKET_COMMAND, cmd->packet->flags,
496 tmpbuf->data, tmpbuf->len, TRUE);
498 /* Reprocess this packet after received reply */
499 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
500 silc_command_get_ident(cmd->payload),
501 silc_server_command_destructor,
502 silc_server_command_whois,
503 silc_server_command_dup(cmd));
506 silc_command_set_ident(cmd->payload, old_ident);
508 silc_buffer_free(tmpbuf);
517 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
518 SilcClientEntry *clients,
519 unsigned int clients_count)
521 SilcServer server = cmd->server;
523 int i, count = 0, len;
524 SilcBuffer packet, idp;
525 SilcClientEntry entry;
526 SilcCommandStatus status;
527 unsigned short ident = silc_command_get_ident(cmd->payload);
529 status = SILC_STATUS_OK;
530 if (clients_count > 1)
531 status = SILC_STATUS_LIST_START;
533 for (i = 0; i < clients_count; i++) {
536 if (entry->connection && entry->data.registered == FALSE) {
537 if (clients_count == 1)
538 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
539 SILC_STATUS_ERR_NO_SUCH_NICK,
541 strlen(entry->nickname));
545 if (count && i - 1 == count)
548 if (clients_count > 2)
549 status = SILC_STATUS_LIST_ITEM;
551 if (clients_count > 1 && i == clients_count - 1)
552 status = SILC_STATUS_LIST_END;
554 /* Sanity check, however these should never fail. However, as
555 this sanity check has been added here they have failed. */
556 if (!entry->nickname || !entry->username)
559 /* Send WHOIS reply */
560 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
561 tmp = silc_argument_get_first_arg(cmd->args, NULL);
564 char nh[256], uh[256];
565 unsigned char idle[4];
566 SilcSocketConnection hsock;
568 memset(uh, 0, sizeof(uh));
569 memset(nh, 0, sizeof(nh));
571 strncat(nh, entry->nickname, strlen(entry->nickname));
572 if (!strchr(entry->nickname, '@')) {
574 len = entry->router ? strlen(entry->router->server_name) :
575 strlen(server->server_name);
576 strncat(nh, entry->router ? entry->router->server_name :
577 server->server_name, len);
580 strncat(uh, entry->username, strlen(entry->username));
581 if (!strchr(entry->username, '@')) {
583 hsock = (SilcSocketConnection)entry->connection;
584 len = strlen(hsock->hostname);
585 strncat(uh, hsock->hostname, len);
588 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
591 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
593 2, idp->data, idp->len,
597 strlen(entry->userinfo),
601 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
602 0, packet->data, packet->len, FALSE);
604 silc_buffer_free(packet);
605 silc_buffer_free(idp);
610 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
612 SilcServer server = cmd->server;
613 char *nick = NULL, *server_name = NULL;
614 int count = 0, clients_count = 0;
615 SilcClientEntry *clients = NULL, entry;
616 SilcClientID **client_id = NULL;
617 unsigned int client_id_count = 0;
620 /* Protocol dictates that we must always send the received WHOIS request
621 to our router if we are normal server, so let's do it now unless we
622 are standalone. We will not send any replies to the client until we
623 have received reply from the router. */
624 if (server->server_type == SILC_SERVER &&
625 !cmd->pending && !server->standalone) {
627 unsigned short old_ident;
629 old_ident = silc_command_get_ident(cmd->payload);
630 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
631 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
633 /* Send WHOIS command to our router */
634 silc_server_packet_send(server, (SilcSocketConnection)
635 server->router->connection,
636 SILC_PACKET_COMMAND, cmd->packet->flags,
637 tmpbuf->data, tmpbuf->len, TRUE);
639 /* Reprocess this packet after received reply from router */
640 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
641 silc_command_get_ident(cmd->payload),
642 silc_server_command_destructor,
643 silc_server_command_whois,
644 silc_server_command_dup(cmd));
647 silc_command_set_ident(cmd->payload, old_ident);
649 silc_buffer_free(tmpbuf);
654 /* We are ready to process the command request. Let's search for the
655 requested client and send reply to the requesting client. */
657 /* Parse the whois request */
658 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
659 &nick, &server_name, &count,
663 /* Get all clients matching that ID or nickname from local list */
664 if (client_id_count) {
665 /* Check all Client ID's received in the command packet */
666 for (i = 0; i < client_id_count; i++) {
667 entry = silc_idlist_find_client_by_id(server->local_list,
670 clients = silc_realloc(clients, sizeof(*clients) *
671 (clients_count + 1));
672 clients[clients_count++] = entry;
676 clients = silc_idlist_get_clients_by_nickname(server->local_list,
680 clients = silc_idlist_get_clients_by_hash(server->local_list,
681 nick, server->md5hash,
685 /* Check global list as well */
687 if (client_id_count) {
688 /* Check all Client ID's received in the command packet */
689 for (i = 0; i < client_id_count; i++) {
690 entry = silc_idlist_find_client_by_id(server->global_list,
693 clients = silc_realloc(clients, sizeof(*clients) *
694 (clients_count + 1));
695 clients[clients_count++] = entry;
699 clients = silc_idlist_get_clients_by_nickname(server->global_list,
703 clients = silc_idlist_get_clients_by_hash(server->global_list,
704 nick, server->md5hash,
710 /* Such client(s) really does not exist in the SILC network. */
711 if (!client_id_count) {
712 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
713 SILC_STATUS_ERR_NO_SUCH_NICK,
714 3, nick, strlen(nick));
716 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
717 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
718 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
719 2, idp->data, idp->len);
720 silc_buffer_free(idp);
725 /* Router always finds the client entry if it exists in the SILC network.
726 However, it might be incomplete entry and does not include all the
727 mandatory fields that WHOIS command reply requires. Check for these and
728 make query from the server who owns the client if some fields are
730 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
735 /* Send the command reply to the client */
736 silc_server_command_whois_send_reply(cmd, clients, clients_count);
739 if (client_id_count) {
740 for (i = 0; i < client_id_count; i++)
741 silc_free(client_id[i]);
742 silc_free(client_id);
749 silc_free(server_name);
755 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
757 SilcServer server = cmd->server;
758 char *nick = NULL, *server_name = NULL;
759 int count = 0, clients_count = 0;
760 SilcClientEntry *clients = NULL, entry;
761 SilcClientID **client_id = NULL;
762 unsigned int client_id_count = 0;
765 /* Parse the whois request */
766 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
767 &nick, &server_name, &count,
771 /* Process the command request. Let's search for the requested client and
772 send reply to the requesting server. */
774 if (client_id_count) {
775 /* Check all Client ID's received in the command packet */
776 for (i = 0; i < client_id_count; i++) {
777 entry = silc_idlist_find_client_by_id(server->local_list,
780 clients = silc_realloc(clients, sizeof(*clients) *
781 (clients_count + 1));
782 clients[clients_count++] = entry;
786 clients = silc_idlist_get_clients_by_nickname(server->local_list,
790 clients = silc_idlist_get_clients_by_hash(server->local_list,
791 nick, server->md5hash,
795 /* If we are router we will check our global list as well. */
796 if (!clients && server->server_type == SILC_ROUTER) {
797 if (client_id_count) {
798 /* Check all Client ID's received in the command packet */
799 for (i = 0; i < client_id_count; i++) {
800 entry = silc_idlist_find_client_by_id(server->global_list,
803 clients = silc_realloc(clients, sizeof(*clients) *
804 (clients_count + 1));
805 clients[clients_count++] = entry;
809 clients = silc_idlist_get_clients_by_nickname(server->global_list,
813 clients = silc_idlist_get_clients_by_hash(server->global_list,
814 nick, server->md5hash,
820 /* Such a client really does not exist in the SILC network. */
821 if (!client_id_count) {
822 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
823 SILC_STATUS_ERR_NO_SUCH_NICK,
824 3, nick, strlen(nick));
826 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
827 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
828 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
829 2, idp->data, idp->len);
830 silc_buffer_free(idp);
835 /* Router always finds the client entry if it exists in the SILC network.
836 However, it might be incomplete entry and does not include all the
837 mandatory fields that WHOIS command reply requires. Check for these and
838 make query from the server who owns the client if some fields are
840 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
845 /* Send the command reply to the client */
846 silc_server_command_whois_send_reply(cmd, clients, clients_count);
849 if (client_id_count) {
850 for (i = 0; i < client_id_count; i++)
851 silc_free(client_id[i]);
852 silc_free(client_id);
859 silc_free(server_name);
864 /* Server side of command WHOIS. Processes user's query and sends found
865 results as command replies back to the client. */
867 SILC_SERVER_CMD_FUNC(whois)
869 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
872 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
874 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
875 ret = silc_server_command_whois_from_client(cmd);
876 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
877 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
878 ret = silc_server_command_whois_from_server(cmd);
881 silc_server_command_free(cmd);
884 /******************************************************************************
888 ******************************************************************************/
891 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
899 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
902 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
906 /* Get the nickname@server string and parse it. */
907 if (strchr(tmp, '@')) {
908 len = strcspn(tmp, "@");
909 *nickname = silc_calloc(len + 1, sizeof(char));
910 memcpy(*nickname, tmp, len);
911 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
912 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
914 *nickname = strdup(tmp);
916 /* Get the max count of reply messages allowed */
917 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
927 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
928 SilcClientEntry *clients,
929 unsigned int clients_count)
931 SilcServer server = cmd->server;
933 int i, count = 0, len;
934 SilcBuffer packet, idp;
935 SilcClientEntry entry = NULL;
936 SilcCommandStatus status;
937 unsigned short ident = silc_command_get_ident(cmd->payload);
940 status = SILC_STATUS_OK;
941 if (clients_count > 1)
942 status = SILC_STATUS_LIST_START;
944 for (i = 0; i < clients_count; i++) {
947 /* We will take only clients that are not valid anymore. They are the
948 ones that are not registered anymore but still have a ID. They
949 have disconnected us, and thus valid for WHOWAS. */
950 if (entry->data.registered == TRUE)
952 if (entry->id == NULL)
955 if (count && i - 1 == count)
960 if (clients_count > 2)
961 status = SILC_STATUS_LIST_ITEM;
963 if (clients_count > 1 && i == clients_count - 1)
964 status = SILC_STATUS_LIST_END;
966 /* Sanity check, however these should never fail. However, as
967 this sanity check has been added here they have failed. */
968 if (!entry->nickname || !entry->username)
971 /* Send WHOWAS reply */
972 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
973 tmp = silc_argument_get_first_arg(cmd->args, NULL);
976 char nh[256], uh[256];
978 memset(uh, 0, sizeof(uh));
979 memset(nh, 0, sizeof(nh));
981 strncat(nh, entry->nickname, strlen(entry->nickname));
982 if (!strchr(entry->nickname, '@')) {
984 len = entry->router ? strlen(entry->router->server_name) :
985 strlen(server->server_name);
986 strncat(nh, entry->router ? entry->router->server_name :
987 server->server_name, len);
990 strncat(uh, entry->username, strlen(entry->username));
991 if (!strchr(entry->username, '@')) {
993 strcat(uh, "*private*");
997 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
999 2, idp->data, idp->len,
1003 strlen(entry->userinfo));
1006 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1007 0, packet->data, packet->len, FALSE);
1009 silc_buffer_free(packet);
1010 silc_buffer_free(idp);
1013 if (found == FALSE && entry)
1014 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1015 SILC_STATUS_ERR_NO_SUCH_NICK,
1017 strlen(entry->nickname));
1021 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1023 SilcServer server = cmd->server;
1024 char *nick = NULL, *server_name = NULL;
1025 int count = 0, clients_count = 0;
1026 SilcClientEntry *clients = NULL;
1029 /* Protocol dictates that we must always send the received WHOWAS request
1030 to our router if we are normal server, so let's do it now unless we
1031 are standalone. We will not send any replies to the client until we
1032 have received reply from the router. */
1033 if (server->server_type == SILC_SERVER &&
1034 !cmd->pending && !server->standalone) {
1036 unsigned short old_ident;
1038 old_ident = silc_command_get_ident(cmd->payload);
1039 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1040 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1042 /* Send WHOWAS command to our router */
1043 silc_server_packet_send(server, (SilcSocketConnection)
1044 server->router->connection,
1045 SILC_PACKET_COMMAND, cmd->packet->flags,
1046 tmpbuf->data, tmpbuf->len, TRUE);
1048 /* Reprocess this packet after received reply from router */
1049 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1050 silc_command_get_ident(cmd->payload),
1051 silc_server_command_destructor,
1052 silc_server_command_whois,
1053 silc_server_command_dup(cmd));
1054 cmd->pending = TRUE;
1056 silc_command_set_ident(cmd->payload, old_ident);
1058 silc_buffer_free(tmpbuf);
1063 /* We are ready to process the command request. Let's search for the
1064 requested client and send reply to the requesting client. */
1066 /* Parse the whowas request */
1067 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1070 /* Get all clients matching that nickname from local list */
1071 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1075 clients = silc_idlist_get_clients_by_hash(server->local_list,
1076 nick, server->md5hash,
1079 /* Check global list as well */
1081 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1085 clients = silc_idlist_get_clients_by_hash(server->global_list,
1086 nick, server->md5hash,
1091 /* Such client(s) really does not exist in the SILC network. */
1092 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1093 SILC_STATUS_ERR_NO_SUCH_NICK,
1094 3, nick, strlen(nick));
1098 /* Send the command reply to the client */
1099 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1107 silc_free(server_name);
1113 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1115 SilcServer server = cmd->server;
1116 char *nick = NULL, *server_name = NULL;
1117 int count = 0, clients_count = 0;
1118 SilcClientEntry *clients = NULL;
1121 /* Parse the whowas request */
1122 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1125 /* Process the command request. Let's search for the requested client and
1126 send reply to the requesting server. */
1128 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1132 clients = silc_idlist_get_clients_by_hash(server->local_list,
1133 nick, server->md5hash,
1136 /* If we are router we will check our global list as well. */
1137 if (!clients && server->server_type == SILC_ROUTER) {
1138 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1142 clients = silc_idlist_get_clients_by_hash(server->global_list,
1143 nick, server->md5hash,
1148 /* Such a client really does not exist in the SILC network. */
1149 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1150 SILC_STATUS_ERR_NO_SUCH_NICK,
1151 3, nick, strlen(nick));
1155 /* Send the command reply to the client */
1156 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1164 silc_free(server_name);
1169 /* Server side of command WHOWAS. */
1171 SILC_SERVER_CMD_FUNC(whowas)
1173 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1176 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1178 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1179 ret = silc_server_command_whowas_from_client(cmd);
1180 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1181 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1182 ret = silc_server_command_whowas_from_server(cmd);
1185 silc_server_command_free(cmd);
1188 /******************************************************************************
1192 ******************************************************************************/
1194 /* Checks that all mandatory fields are present. If not then send WHOIS
1195 request to the server who owns the client. We use WHOIS because we want
1196 to get as much information as possible at once. */
1199 silc_server_command_identify_check(SilcServerCommandContext cmd,
1200 SilcClientEntry *clients,
1201 unsigned int clients_count)
1203 SilcServer server = cmd->server;
1205 SilcClientEntry entry;
1207 for (i = 0; i < clients_count; i++) {
1210 if (!entry->nickname) {
1212 unsigned short old_ident;
1217 old_ident = silc_command_get_ident(cmd->payload);
1218 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1219 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1220 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1222 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1223 now anyway so make it a good one. */
1224 silc_server_packet_send(server, entry->router->connection,
1225 SILC_PACKET_COMMAND, cmd->packet->flags,
1226 tmpbuf->data, tmpbuf->len, TRUE);
1228 /* Reprocess this packet after received reply */
1229 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1230 silc_command_get_ident(cmd->payload),
1231 silc_server_command_destructor,
1232 silc_server_command_identify,
1233 silc_server_command_dup(cmd));
1235 cmd->pending = TRUE;
1237 /* Put old data back to the Command Payload we just changed */
1238 silc_command_set_ident(cmd->payload, old_ident);
1239 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1241 silc_buffer_free(tmpbuf);
1250 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1251 SilcClientEntry *clients,
1252 unsigned int clients_count)
1254 SilcServer server = cmd->server;
1256 int i, count = 0, len;
1257 SilcBuffer packet, idp;
1258 SilcClientEntry entry;
1259 SilcCommandStatus status;
1260 unsigned short ident = silc_command_get_ident(cmd->payload);
1262 status = SILC_STATUS_OK;
1263 if (clients_count > 1)
1264 status = SILC_STATUS_LIST_START;
1266 for (i = 0; i < clients_count; i++) {
1269 if (entry->connection && entry->data.registered == FALSE) {
1270 if (clients_count == 1)
1271 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1272 SILC_STATUS_ERR_NO_SUCH_NICK,
1274 strlen(entry->nickname));
1278 if (count && i - 1 == count)
1281 if (clients_count > 2)
1282 status = SILC_STATUS_LIST_ITEM;
1284 if (clients_count > 1 && i == clients_count - 1)
1285 status = SILC_STATUS_LIST_END;
1287 /* Send IDENTIFY reply */
1288 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1289 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1293 char nh[256], uh[256];
1294 SilcSocketConnection hsock;
1296 memset(uh, 0, sizeof(uh));
1297 memset(nh, 0, sizeof(nh));
1299 strncat(nh, entry->nickname, strlen(entry->nickname));
1300 if (!strchr(entry->nickname, '@')) {
1301 strncat(nh, "@", 1);
1302 len = entry->router ? strlen(entry->router->server_name) :
1303 strlen(server->server_name);
1304 strncat(nh, entry->router ? entry->router->server_name :
1305 server->server_name, len);
1308 if (!entry->username) {
1309 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1311 2, idp->data, idp->len,
1314 strncat(uh, entry->username, strlen(entry->username));
1315 if (!strchr(entry->username, '@')) {
1316 strncat(uh, "@", 1);
1317 hsock = (SilcSocketConnection)entry->connection;
1318 len = strlen(hsock->hostname);
1319 strncat(uh, hsock->hostname, len);
1322 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1324 2, idp->data, idp->len,
1329 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1330 0, packet->data, packet->len, FALSE);
1332 silc_buffer_free(packet);
1333 silc_buffer_free(idp);
1339 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1341 SilcServer server = cmd->server;
1342 char *nick = NULL, *server_name = NULL;
1343 int count = 0, clients_count = 0;
1344 SilcClientEntry *clients = NULL, entry;
1345 SilcClientID **client_id = NULL;
1346 unsigned int client_id_count = 0;
1349 /* Protocol dictates that we must always send the received IDENTIFY request
1350 to our router if we are normal server, so let's do it now unless we
1351 are standalone. We will not send any replies to the client until we
1352 have received reply from the router. */
1353 if (server->server_type == SILC_SERVER &&
1354 !cmd->pending && !server->standalone) {
1356 unsigned short old_ident;
1358 old_ident = silc_command_get_ident(cmd->payload);
1359 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1360 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1362 /* Send IDENTIFY command to our router */
1363 silc_server_packet_send(server, (SilcSocketConnection)
1364 server->router->connection,
1365 SILC_PACKET_COMMAND, cmd->packet->flags,
1366 tmpbuf->data, tmpbuf->len, TRUE);
1368 /* Reprocess this packet after received reply from router */
1369 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1370 silc_command_get_ident(cmd->payload),
1371 silc_server_command_destructor,
1372 silc_server_command_identify,
1373 silc_server_command_dup(cmd));
1374 cmd->pending = TRUE;
1376 silc_command_set_ident(cmd->payload, old_ident);
1378 silc_buffer_free(tmpbuf);
1383 /* We are ready to process the command request. Let's search for the
1384 requested client and send reply to the requesting client. */
1386 /* Parse the IDENTIFY request */
1387 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1388 &nick, &server_name, &count,
1389 SILC_COMMAND_IDENTIFY))
1392 /* Get all clients matching that ID or nickname from local list */
1393 if (client_id_count) {
1394 /* Check all Client ID's received in the command packet */
1395 for (i = 0; i < client_id_count; i++) {
1396 entry = silc_idlist_find_client_by_id(server->local_list,
1397 client_id[i], NULL);
1399 clients = silc_realloc(clients, sizeof(*clients) *
1400 (clients_count + 1));
1401 clients[clients_count++] = entry;
1405 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1409 clients = silc_idlist_get_clients_by_hash(server->local_list,
1410 nick, server->md5hash,
1414 /* Check global list as well */
1416 if (client_id_count) {
1417 /* Check all Client ID's received in the command packet */
1418 for (i = 0; i < client_id_count; i++) {
1419 entry = silc_idlist_find_client_by_id(server->global_list,
1420 client_id[i], NULL);
1422 clients = silc_realloc(clients, sizeof(*clients) *
1423 (clients_count + 1));
1424 clients[clients_count++] = entry;
1428 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1432 clients = silc_idlist_get_clients_by_hash(server->global_list,
1433 nick, server->md5hash,
1439 /* Such a client really does not exist in the SILC network. */
1440 if (!client_id_count) {
1441 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1442 SILC_STATUS_ERR_NO_SUCH_NICK,
1443 3, nick, strlen(nick));
1445 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1446 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1447 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1448 2, idp->data, idp->len);
1449 silc_buffer_free(idp);
1454 /* Check that all mandatory fields are present and request those data
1455 from the server who owns the client if necessary. */
1456 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1461 /* Send the command reply to the client */
1462 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1465 if (client_id_count) {
1466 for (i = 0; i < client_id_count; i++)
1467 silc_free(client_id[i]);
1468 silc_free(client_id);
1475 silc_free(server_name);
1481 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1483 SilcServer server = cmd->server;
1484 char *nick = NULL, *server_name = NULL;
1485 int count = 0, clients_count = 0;
1486 SilcClientEntry *clients = NULL, entry;
1487 SilcClientID **client_id = NULL;
1488 unsigned int client_id_count = 0;
1491 /* Parse the IDENTIFY request */
1492 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1493 &nick, &server_name, &count,
1494 SILC_COMMAND_IDENTIFY))
1497 /* Process the command request. Let's search for the requested client and
1498 send reply to the requesting server. */
1500 if (client_id_count) {
1501 /* Check all Client ID's received in the command packet */
1502 for (i = 0; i < client_id_count; i++) {
1503 entry = silc_idlist_find_client_by_id(server->local_list,
1504 client_id[i], NULL);
1506 clients = silc_realloc(clients, sizeof(*clients) *
1507 (clients_count + 1));
1508 clients[clients_count++] = entry;
1512 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1516 clients = silc_idlist_get_clients_by_hash(server->local_list,
1517 nick, server->md5hash,
1521 /* If we are router we will check our global list as well. */
1522 if (!clients && server->server_type == SILC_ROUTER) {
1523 if (client_id_count) {
1524 /* Check all Client ID's received in the command packet */
1525 for (i = 0; i < client_id_count; i++) {
1526 entry = silc_idlist_find_client_by_id(server->global_list,
1527 client_id[i], NULL);
1529 clients = silc_realloc(clients, sizeof(*clients) *
1530 (clients_count + 1));
1531 clients[clients_count++] = entry;
1535 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1539 clients = silc_idlist_get_clients_by_hash(server->global_list,
1540 nick, server->md5hash,
1546 /* Such a client really does not exist in the SILC network. */
1547 if (!client_id_count) {
1548 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1549 SILC_STATUS_ERR_NO_SUCH_NICK,
1550 3, nick, strlen(nick));
1552 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1553 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1554 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1555 2, idp->data, idp->len);
1556 silc_buffer_free(idp);
1561 /* Check that all mandatory fields are present and request those data
1562 from the server who owns the client if necessary. */
1563 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1568 /* Send the command reply */
1569 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1572 if (client_id_count) {
1573 for (i = 0; i < client_id_count; i++)
1574 silc_free(client_id[i]);
1575 silc_free(client_id);
1582 silc_free(server_name);
1587 SILC_SERVER_CMD_FUNC(identify)
1589 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1592 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1594 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1595 ret = silc_server_command_identify_from_client(cmd);
1596 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1597 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1598 ret = silc_server_command_identify_from_server(cmd);
1601 silc_server_command_free(cmd);
1604 /* Checks string for bad characters and returns TRUE if they are found. */
1606 static int silc_server_command_bad_chars(char *nick)
1608 if (strchr(nick, '\\')) return TRUE;
1609 if (strchr(nick, '\"')) return TRUE;
1610 if (strchr(nick, '´')) return TRUE;
1611 if (strchr(nick, '`')) return TRUE;
1612 if (strchr(nick, '\'')) return TRUE;
1613 if (strchr(nick, '*')) return TRUE;
1614 if (strchr(nick, '/')) return TRUE;
1615 if (strchr(nick, '@')) return TRUE;
1620 /* Server side of command NICK. Sets nickname for user. Setting
1621 nickname causes generation of a new client ID for the client. The
1622 new client ID is sent to the client after changing the nickname. */
1624 SILC_SERVER_CMD_FUNC(nick)
1626 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1627 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1628 SilcServer server = cmd->server;
1629 SilcBuffer packet, nidp, oidp;
1630 SilcClientID *new_id;
1633 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1636 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1638 /* Check nickname */
1639 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1640 if (silc_server_command_bad_chars(nick) == TRUE) {
1641 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1642 SILC_STATUS_ERR_BAD_NICKNAME);
1646 if (strlen(nick) > 128)
1649 /* Create new Client ID */
1650 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1651 cmd->server->md5hash, nick,
1654 /* Send notify about nickname change to our router. We send the new
1655 ID and ask to replace it with the old one. If we are router the
1656 packet is broadcasted. Send NICK_CHANGE notify. */
1657 if (!server->standalone)
1658 silc_server_send_notify_nick_change(server, server->router->connection,
1659 server->server_type == SILC_SERVER ?
1660 FALSE : TRUE, client->id,
1661 new_id, SILC_ID_CLIENT_LEN);
1663 /* Remove old cache entry */
1664 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1667 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1671 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1672 silc_free(client->id);
1675 /* Save the nickname as this client is our local client */
1676 if (client->nickname)
1677 silc_free(client->nickname);
1679 client->nickname = strdup(nick);
1680 client->id = new_id;
1682 /* Update client cache */
1683 silc_idcache_add(server->local_list->clients, client->nickname,
1684 SILC_ID_CLIENT, client->id, (void *)client, TRUE, FALSE);
1686 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1688 /* Send NICK_CHANGE notify to the client's channels */
1689 silc_server_send_notify_on_channels(server, NULL, client,
1690 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1691 oidp->data, oidp->len,
1692 nidp->data, nidp->len);
1694 /* Send the new Client ID as reply command back to client */
1695 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1696 SILC_STATUS_OK, 0, 1,
1697 2, nidp->data, nidp->len);
1698 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1699 0, packet->data, packet->len, FALSE);
1701 silc_buffer_free(packet);
1702 silc_buffer_free(nidp);
1703 silc_buffer_free(oidp);
1706 silc_server_command_free(cmd);
1709 SILC_SERVER_CMD_FUNC(list)
1713 /* Server side of TOPIC command. Sets topic for channel and/or returns
1714 current topic to client. */
1716 SILC_SERVER_CMD_FUNC(topic)
1718 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1719 SilcServer server = cmd->server;
1720 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1721 SilcChannelID *channel_id;
1722 SilcChannelEntry channel;
1723 SilcChannelClientEntry chl;
1724 SilcBuffer packet, idp;
1726 unsigned int argc, tmp_len;
1728 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1730 argc = silc_argument_get_arg_num(cmd->args);
1732 /* Get Channel ID */
1733 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1736 SILC_STATUS_ERR_NO_CHANNEL_ID);
1739 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1741 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1742 SILC_STATUS_ERR_NO_CHANNEL_ID);
1746 /* Check whether the channel exists */
1747 channel = silc_idlist_find_channel_by_id(server->local_list,
1750 channel = silc_idlist_find_channel_by_id(server->global_list,
1753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1754 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1761 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1764 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1768 if (strlen(tmp) > 256) {
1769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1770 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1774 /* See whether has rights to change topic */
1775 silc_list_start(channel->user_list);
1776 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1777 if (chl->client == client)
1780 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1781 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1783 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1788 /* Set the topic for channel */
1790 silc_free(channel->topic);
1791 channel->topic = strdup(tmp);
1793 /* Send TOPIC_SET notify type to the network */
1794 if (!server->standalone)
1795 silc_server_send_notify_topic_set(server, server->router->connection,
1796 server->server_type == SILC_ROUTER ?
1797 TRUE : FALSE, channel, client->id,
1798 SILC_ID_CLIENT_LEN, channel->topic);
1800 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1802 /* Send notify about topic change to all clients on the channel */
1803 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1804 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1805 idp->data, idp->len,
1806 channel->topic, strlen(channel->topic));
1807 silc_buffer_free(idp);
1810 /* Send the topic to client as reply packet */
1811 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1813 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1814 SILC_STATUS_OK, 0, 2,
1815 2, idp->data, idp->len,
1817 strlen(channel->topic));
1819 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1820 SILC_STATUS_OK, 0, 1,
1821 2, idp->data, idp->len);
1822 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1823 0, packet->data, packet->len, FALSE);
1825 silc_buffer_free(packet);
1826 silc_buffer_free(idp);
1827 silc_free(channel_id);
1830 silc_server_command_free(cmd);
1833 /* Server side of INVITE command. Invites some client to join some channel. */
1835 SILC_SERVER_CMD_FUNC(invite)
1837 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1838 SilcServer server = cmd->server;
1839 SilcSocketConnection sock = cmd->sock, dest_sock;
1840 SilcClientEntry sender, dest;
1841 SilcClientID *dest_id;
1842 SilcChannelEntry channel;
1843 SilcChannelID *channel_id;
1848 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1850 /* Get destination ID */
1851 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1853 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1854 SILC_STATUS_ERR_NO_CLIENT_ID);
1857 dest_id = silc_id_payload_parse_id(tmp, len);
1859 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1860 SILC_STATUS_ERR_NO_CLIENT_ID);
1864 /* Get Channel ID */
1865 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1867 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1868 SILC_STATUS_ERR_NO_CHANNEL_ID);
1871 channel_id = silc_id_payload_parse_id(tmp, len);
1873 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1874 SILC_STATUS_ERR_NO_CHANNEL_ID);
1878 /* Check whether the channel exists */
1879 channel = silc_idlist_find_channel_by_id(server->local_list,
1882 channel = silc_idlist_find_channel_by_id(server->global_list,
1885 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1886 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1891 /* Check whether the sender of this command is on the channel. */
1892 sender = (SilcClientEntry)sock->user_data;
1893 if (!silc_server_client_on_channel(sender, channel)) {
1894 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1895 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1899 /* Check whether the channel is invite-only channel. If yes then the
1900 sender of this command must be at least channel operator. */
1901 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1902 SilcChannelClientEntry chl;
1904 silc_list_start(channel->user_list);
1905 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1906 if (chl->client == sender) {
1907 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1908 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1909 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1916 /* Find the connection data for the destination. If it is local we will
1917 send it directly otherwise we will send it to router for routing. */
1918 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1920 dest_sock = (SilcSocketConnection)dest->connection;
1922 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1924 /* Check whether the requested client is already on the channel. */
1925 /* XXX if we are normal server we don't know about global clients on
1926 the channel thus we must request it (USERS command), check from
1927 local cache as well. */
1928 if (silc_server_client_on_channel(dest, channel)) {
1929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1930 SILC_STATUS_ERR_USER_ON_CHANNEL);
1934 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1936 /* Send notify to the client that is invited to the channel */
1937 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1939 SILC_NOTIFY_TYPE_INVITE, 2,
1940 sidp->data, sidp->len, tmp, len);
1942 /* Send command reply */
1943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1946 silc_buffer_free(sidp);
1949 silc_server_command_free(cmd);
1954 SilcSocketConnection sock;
1958 /* Quits connection to client. This gets called if client won't
1959 close the connection even when it has issued QUIT command. */
1961 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1963 QuitInternal q = (QuitInternal)context;
1965 /* Free all client specific data, such as client entry and entires
1966 on channels this client may be on. */
1967 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1969 q->sock->user_data = NULL;
1971 /* Close the connection on our side */
1972 silc_server_close_connection(q->server, q->sock);
1974 silc_free(q->signoff);
1978 /* Quits SILC session. This is the normal way to disconnect client. */
1980 SILC_SERVER_CMD_FUNC(quit)
1982 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1983 SilcServer server = cmd->server;
1984 SilcSocketConnection sock = cmd->sock;
1986 unsigned char *tmp = NULL;
1987 unsigned int len = 0;
1989 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
1991 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1994 /* Get destination ID */
1995 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1999 q = silc_calloc(1, sizeof(*q));
2002 q->signoff = tmp ? strdup(tmp) : NULL;
2004 /* We quit the connection with little timeout */
2005 silc_task_register(server->timeout_queue, sock->sock,
2006 silc_server_command_quit_cb, (void *)q,
2007 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2010 silc_server_command_free(cmd);
2013 /* Server side of command KILL. This command is used by router operator
2014 to remove an client from the SILC Network temporarily. */
2016 SILC_SERVER_CMD_FUNC(kill)
2018 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2019 SilcServer server = cmd->server;
2020 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2021 SilcClientEntry remote_client;
2022 SilcClientID *client_id;
2023 unsigned char *tmp, *comment;
2024 unsigned int tmp_len;
2027 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2029 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2032 if (server->server_type != SILC_ROUTER)
2035 /* Check whether client has the permissions. */
2036 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2038 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2042 /* Get the client ID */
2043 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2045 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2046 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2049 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2052 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2056 /* Get the client entry */
2057 remote_client = silc_idlist_find_client_by_id(server->local_list,
2059 if (!remote_client) {
2060 remote_client = silc_idlist_find_client_by_id(server->global_list,
2062 if (!remote_client) {
2063 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2064 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2070 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2072 /* Send reply to the sender */
2073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2076 /* Send KILLED notify to the channels. It is not sent to the client
2077 as it will be sent differently destined directly to the client and not
2079 idp = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
2080 silc_server_send_notify_on_channels(server, remote_client->connection,
2081 remote_client, SILC_NOTIFY_TYPE_KILLED,
2083 idp->data, idp->len,
2084 comment, comment ? strlen(comment) : 0);
2085 silc_buffer_free(idp);
2087 /* Remove the client from all channels. This generates new keys to the
2088 channels as well. */
2089 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2092 /* Send KILLED notify to the client directly */
2093 silc_server_send_notify_killed(server, remote_client->connection ?
2094 remote_client->connection :
2095 remote_client->router->connection, FALSE,
2096 remote_client->id, SILC_ID_CLIENT_LEN,
2099 /* Send KILLED notify to primary route */
2100 if (!server->standalone)
2101 silc_server_send_notify_killed(server, server->router->connection,
2102 server->server_type == SILC_ROUTER ?
2104 remote_client->id, SILC_ID_CLIENT_LEN,
2108 silc_server_command_free(cmd);
2111 /* Server side of command INFO. This sends information about us to
2112 the client. If client requested specific server we will send the
2113 command to that server. */
2115 SILC_SERVER_CMD_FUNC(info)
2117 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2118 SilcServer server = cmd->server;
2119 SilcBuffer packet, idp;
2120 char info_string[256], *dest_server;
2122 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
2124 /* Get server name */
2125 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2127 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2128 SILC_STATUS_ERR_NO_SUCH_SERVER);
2132 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2133 /* Send our reply */
2134 memset(info_string, 0, sizeof(info_string));
2135 snprintf(info_string, sizeof(info_string),
2136 "location: %s server: %s admin: %s <%s>",
2137 server->config->admin_info->location,
2138 server->config->admin_info->server_type,
2139 server->config->admin_info->admin_name,
2140 server->config->admin_info->admin_email);
2142 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2144 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2145 SILC_STATUS_OK, 0, 2,
2146 2, idp->data, idp->len,
2148 strlen(info_string));
2149 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2150 packet->data, packet->len, FALSE);
2152 silc_buffer_free(packet);
2153 silc_buffer_free(idp);
2155 /* Send this command to the requested server */
2157 if (server->server_type == SILC_SERVER && !server->standalone) {
2161 if (server->server_type == SILC_ROUTER) {
2167 silc_server_command_free(cmd);
2170 /* Server side of command PING. This just replies to the ping. */
2172 SILC_SERVER_CMD_FUNC(ping)
2174 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2175 SilcServer server = cmd->server;
2180 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2183 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2185 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2186 SILC_STATUS_ERR_NO_SERVER_ID);
2189 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2193 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2194 /* Send our reply */
2195 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2198 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2199 SILC_STATUS_ERR_NO_SUCH_SERVER);
2206 silc_server_command_free(cmd);
2209 /* Internal routine to join channel. The channel sent to this function
2210 has been either created or resolved from ID lists. This joins the sent
2211 client to the channel. */
2213 static void silc_server_command_join_channel(SilcServer server,
2214 SilcServerCommandContext cmd,
2215 SilcChannelEntry channel,
2216 SilcClientID *client_id,
2220 SilcSocketConnection sock = cmd->sock;
2222 unsigned int tmp_len, user_count;
2223 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2224 SilcClientEntry client;
2225 SilcChannelClientEntry chl;
2226 SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
2227 unsigned short ident = silc_command_get_ident(cmd->payload);
2229 SILC_LOG_DEBUG(("Start"));
2234 /* Get passphrase */
2235 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2237 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2238 memcpy(passphrase, tmp, tmp_len);
2242 * Check channel modes
2245 /* Check invite list if channel is invite-only channel */
2246 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2247 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2248 /* Invite list is specified. Check whether client is invited in the
2249 list. If not, then check whether it has been invited otherwise. */
2252 /* XXX client must be invited to be able to join the channel */
2256 /* Check ban list if set */
2257 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2261 /* Check the channel passphrase if set. */
2262 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2263 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
2264 strlen(channel->mode_data.passphrase))) {
2265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2266 SILC_STATUS_ERR_BAD_PASSWORD);
2271 /* Check user count limit if set. */
2272 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2273 if (silc_list_count(channel->user_list) + 1 >
2274 channel->mode_data.user_limit) {
2275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2276 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2282 * Client is allowed to join to the channel. Make it happen.
2285 /* Get the client entry */
2286 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2287 client = (SilcClientEntry)sock->user_data;
2289 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2292 /* XXX actually this is useless since router finds always cell's
2293 local clients from its local lists. */
2294 client = silc_idlist_find_client_by_id(server->global_list, client_id,
2301 /* Check whether the client already is on the channel */
2302 if (silc_server_client_on_channel(client, channel)) {
2303 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2304 SILC_STATUS_ERR_USER_ON_CHANNEL);
2308 /* Generate new channel key as protocol dictates */
2309 if ((!created && silc_list_count(channel->user_list) > 0) ||
2310 !channel->channel_key)
2311 silc_server_create_channel_key(server, channel, 0);
2313 /* Send the channel key. This is broadcasted to the channel but is not
2314 sent to the client who is joining to the channel. */
2315 silc_server_send_channel_key(server, NULL, channel,
2316 server->server_type == SILC_ROUTER ?
2317 FALSE : !server->standalone);
2319 /* Join the client to the channel by adding it to channel's user list.
2320 Add also the channel to client entry's channels list for fast cross-
2322 chl = silc_calloc(1, sizeof(*chl));
2324 chl->client = client;
2325 chl->channel = channel;
2326 silc_list_add(channel->user_list, chl);
2327 silc_list_add(client->channels, chl);
2329 /* Get users on the channel */
2330 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2333 /* Encode Client ID Payload of the original client who wants to join */
2334 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2336 /* Encode command reply packet */
2337 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2338 SILC_PUT32_MSB(channel->mode, mode);
2339 SILC_PUT32_MSB(created, tmp2);
2340 SILC_PUT32_MSB(user_count, tmp3);
2341 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2342 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2343 strlen(channel->channel_key->
2345 channel->channel_key->cipher->name,
2346 channel->key_len / 8, channel->key);
2348 if (!channel->topic) {
2350 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2351 SILC_STATUS_OK, ident, 9,
2352 2, channel->channel_name,
2353 strlen(channel->channel_name),
2354 3, chidp->data, chidp->len,
2355 4, clidp->data, clidp->len,
2358 7, keyp->data, keyp->len,
2360 13, user_list->data, user_list->len,
2361 14, mode_list->data,
2365 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2366 SILC_STATUS_OK, ident, 10,
2367 2, channel->channel_name,
2368 strlen(channel->channel_name),
2369 3, chidp->data, chidp->len,
2370 4, clidp->data, clidp->len,
2373 7, keyp->data, keyp->len,
2375 strlen(channel->topic),
2377 13, user_list->data, user_list->len,
2378 14, mode_list->data,
2382 /* Send command reply */
2383 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2384 reply->data, reply->len, FALSE);
2386 if (!cmd->pending) {
2387 /* Send JOIN notify to locally connected clients on the channel */
2388 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2389 SILC_NOTIFY_TYPE_JOIN, 2,
2390 clidp->data, clidp->len,
2391 chidp->data, chidp->len);
2393 /* Send JOIN notify packet to our primary router */
2394 if (!server->standalone)
2395 silc_server_send_notify_join(server, server->router->connection,
2396 server->server_type == SILC_ROUTER ?
2397 TRUE : FALSE, channel, client->id,
2398 SILC_ID_CLIENT_LEN);
2401 silc_buffer_free(reply);
2402 silc_buffer_free(clidp);
2403 silc_buffer_free(chidp);
2404 silc_buffer_free(keyp);
2405 silc_buffer_free(user_list);
2406 silc_buffer_free(mode_list);
2410 silc_free(passphrase);
2413 /* Server side of command JOIN. Joins client into requested channel. If
2414 the channel does not exist it will be created. */
2416 SILC_SERVER_CMD_FUNC(join)
2418 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2419 SilcServer server = cmd->server;
2421 char *tmp, *channel_name = NULL, *cipher, *hmac;
2422 SilcChannelEntry channel;
2423 unsigned int umode = 0;
2424 int created = FALSE;
2425 SilcClientID *client_id;
2427 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2429 /* Get channel name */
2430 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2433 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2438 if (strlen(channel_name) > 256)
2439 channel_name[255] = '\0';
2441 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2443 SILC_STATUS_ERR_BAD_CHANNEL);
2444 silc_free(channel_name);
2448 /* Get Client ID of the client who is joining to the channel */
2449 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2451 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2452 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2455 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2458 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2462 /* Get cipher and hmac name */
2463 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2464 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2466 /* See if the channel exists */
2467 channel = silc_idlist_find_channel_by_name(server->local_list,
2468 channel_name, NULL);
2470 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2471 /* If this is coming from client the Client ID in the command packet must
2472 be same as the client's ID. */
2473 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2474 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2475 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2477 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2483 /* Channel not found */
2485 /* If we are standalone server we don't have a router, we just create
2486 the channel by ourselves. */
2487 if (server->standalone) {
2488 channel = silc_server_create_new_channel(server, server->id, cipher,
2489 hmac, channel_name, TRUE);
2490 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2495 /* The channel does not exist on our server. If we are normal server
2496 we will send JOIN command to our router which will handle the
2497 joining procedure (either creates the channel if it doesn't exist
2498 or joins the client to it). */
2499 if (server->server_type == SILC_SERVER) {
2501 unsigned short old_ident;
2503 old_ident = silc_command_get_ident(cmd->payload);
2504 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2505 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2507 /* Send JOIN command to our router */
2508 silc_server_packet_send(server, (SilcSocketConnection)
2509 server->router->connection,
2510 SILC_PACKET_COMMAND, cmd->packet->flags,
2511 tmpbuf->data, tmpbuf->len, TRUE);
2513 /* Reprocess this packet after received reply from router */
2514 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2515 silc_command_get_ident(cmd->payload),
2516 silc_server_command_destructor,
2517 silc_server_command_join,
2518 silc_server_command_dup(cmd));
2519 cmd->pending = TRUE;
2523 /* We are router and the channel does not seem exist so we will check
2524 our global list as well for the channel. */
2525 channel = silc_idlist_find_channel_by_name(server->global_list,
2526 channel_name, NULL);
2528 /* Channel really does not exist, create it */
2529 channel = silc_server_create_new_channel(server, server->id, cipher,
2530 hmac, channel_name, TRUE);
2531 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2538 /* Channel not found */
2540 /* If the command came from router and/or we are normal server then
2541 something went wrong with the joining as the channel was not found.
2542 We can't do anything else but ignore this. */
2543 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2544 server->server_type == SILC_SERVER)
2547 /* We are router and the channel does not seem exist so we will check
2548 our global list as well for the channel. */
2549 channel = silc_idlist_find_channel_by_name(server->global_list,
2550 channel_name, NULL);
2552 /* Channel really does not exist, create it */
2553 channel = silc_server_create_new_channel(server, server->id, cipher,
2554 hmac, channel_name, TRUE);
2555 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2561 /* If the channel does not have global users and is also empty it means the
2562 channel was created globally (by our router) and the client will be the
2563 channel founder and operator. */
2564 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2565 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2566 created = TRUE; /* Created globally by our router */
2569 /* Join to the channel */
2570 silc_server_command_join_channel(server, cmd, channel, client_id,
2573 silc_free(client_id);
2576 silc_server_command_free(cmd);
2579 /* Server side of command MOTD. Sends server's current "message of the
2580 day" to the client. */
2582 SILC_SERVER_CMD_FUNC(motd)
2584 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2585 SilcServer server = cmd->server;
2589 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2591 /* XXX show currently only our motd */
2593 if (server->config && server->config->motd &&
2594 server->config->motd->motd_file) {
2597 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2602 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2608 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2613 silc_server_command_free(cmd);
2616 SILC_SERVER_CMD_FUNC(umode)
2620 /* Checks that client has rights to add or remove channel modes. If any
2621 of the checks fails FALSE is returned. */
2623 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2624 SilcChannelClientEntry client,
2627 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2628 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2630 /* Check whether has rights to change anything */
2631 if (!is_op && !is_fo)
2634 /* Check whether has rights to change everything */
2638 /* We know that client is channel operator, check that they are not
2639 changing anything that requires channel founder rights. Rest of the
2640 modes are available automatically for channel operator. */
2642 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2643 if (is_op && !is_fo)
2646 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2647 if (is_op && !is_fo)
2652 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2653 if (is_op && !is_fo)
2656 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2657 if (is_op && !is_fo)
2662 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2663 if (is_op && !is_fo)
2666 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2667 if (is_op && !is_fo)
2675 /* Server side command of CMODE. Changes channel mode */
2677 SILC_SERVER_CMD_FUNC(cmode)
2679 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2680 SilcServer server = cmd->server;
2681 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2682 SilcChannelID *channel_id;
2683 SilcChannelEntry channel;
2684 SilcChannelClientEntry chl;
2685 SilcBuffer packet, cidp;
2686 unsigned char *tmp, *tmp_id, *tmp_mask;
2687 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2689 SILC_LOG_DEBUG(("Start"));
2691 argc = silc_argument_get_arg_num(cmd->args);
2693 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2694 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2699 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2703 /* Get Channel ID */
2704 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2707 SILC_STATUS_ERR_NO_CHANNEL_ID);
2710 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2712 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2713 SILC_STATUS_ERR_NO_CHANNEL_ID);
2717 /* Get the channel mode mask */
2718 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2721 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2724 SILC_GET32_MSB(mode_mask, tmp_mask);
2726 /* Get channel entry */
2727 channel = silc_idlist_find_channel_by_id(server->local_list,
2730 channel = silc_idlist_find_channel_by_id(server->global_list,
2733 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2734 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2739 /* Check whether this client is on the channel */
2740 if (!silc_server_client_on_channel(client, channel)) {
2741 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2742 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2746 /* Get entry to the channel user list */
2747 silc_list_start(channel->user_list);
2748 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2749 if (chl->client == client)
2752 /* Check that client has rights to change any requested channel modes */
2753 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2754 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2755 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2760 * Check the modes. Modes that requires nothing special operation are
2764 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2765 /* Channel uses private keys to protect traffic. Client(s) has set the
2766 key locally they want to use, server does not know that key. */
2767 /* Nothing interesting to do here now */
2769 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2770 /* The mode is removed and we need to generate and distribute
2771 new channel key. Clients are not using private channel keys
2772 anymore after this. */
2774 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2777 /* Re-generate channel key */
2778 silc_server_create_channel_key(server, channel, 0);
2780 /* Encode channel key payload to be distributed on the channel */
2782 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2783 strlen(channel->channel_key->
2785 channel->channel_key->cipher->name,
2786 channel->key_len / 8, channel->key);
2788 /* If we are normal server then we will send it to our router. If we
2789 are router we will send it to all local servers that has clients on
2791 if (server->server_type == SILC_SERVER) {
2792 if (!server->standalone)
2793 silc_server_packet_send(server,
2794 cmd->server->router->connection,
2795 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2801 /* Send to locally connected clients on the channel */
2802 silc_server_packet_send_local_channel(server, channel,
2803 SILC_PACKET_CHANNEL_KEY, 0,
2804 packet->data, packet->len, FALSE);
2805 silc_buffer_free(packet);
2809 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2810 /* User limit is set on channel */
2811 unsigned int user_limit;
2813 /* Get user limit */
2814 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2816 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2818 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2822 SILC_GET32_MSB(user_limit, tmp);
2823 channel->mode_data.user_limit = user_limit;
2826 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2827 /* User limit mode is unset. Remove user limit */
2828 channel->mode_data.user_limit = 0;
2831 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2832 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2833 /* Passphrase has been set to channel */
2835 /* Get the passphrase */
2836 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2838 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2839 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2843 /* Save the passphrase */
2844 channel->mode_data.passphrase = strdup(tmp);
2847 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2848 /* Passphrase mode is unset. remove the passphrase */
2849 if (channel->mode_data.passphrase) {
2850 silc_free(channel->mode_data.passphrase);
2851 channel->mode_data.passphrase = NULL;
2856 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2857 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2858 /* Ban list is specified for channel */
2861 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2863 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2864 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2868 /* XXX check that channel founder is not banned */
2870 /* Save the ban list */
2871 channel->mode_data.ban_list = strdup(tmp);
2874 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2875 /* Ban mode is unset. Remove the entire ban list */
2876 if (channel->mode_data.ban_list) {
2877 silc_free(channel->mode_data.ban_list);
2878 channel->mode_data.ban_list = NULL;
2883 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2884 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2885 /* Invite list is specified for channel */
2887 /* Get invite list */
2888 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2891 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2895 /* Save the invite linst */
2896 channel->mode_data.invite_list = strdup(tmp);
2899 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2900 /* Invite list mode is unset. Remove the entire invite list */
2901 if (channel->mode_data.invite_list) {
2902 silc_free(channel->mode_data.invite_list);
2903 channel->mode_data.invite_list = NULL;
2908 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2909 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2910 /* Cipher to use protect the traffic */
2911 unsigned int key_len;
2914 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2916 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2917 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2921 /* XXX Duplicated code, make own function for this!! */
2923 /* Delete old cipher and allocate the new one */
2924 silc_cipher_free(channel->channel_key);
2925 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
2926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2927 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2930 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
2932 /* Re-generate channel key */
2933 silc_server_create_channel_key(server, channel, key_len);
2935 /* Encode channel key payload to be distributed on the channel */
2937 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2938 strlen(channel->channel_key->
2940 channel->channel_key->cipher->name,
2941 channel->key_len / 8, channel->key);
2943 /* If we are normal server then we will send it to our router. If we
2944 are router we will send it to all local servers that has clients on
2946 if (server->server_type == SILC_SERVER) {
2947 if (!server->standalone)
2948 silc_server_packet_send(server,
2949 cmd->server->router->connection,
2950 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2956 /* Send to locally connected clients on the channel */
2957 silc_server_packet_send_local_channel(server, channel,
2958 SILC_PACKET_CHANNEL_KEY, 0,
2959 packet->data, packet->len, FALSE);
2960 silc_buffer_free(packet);
2963 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2964 /* Cipher mode is unset. Remove the cipher and revert back to
2967 if (channel->mode_data.cipher) {
2968 silc_free(channel->mode_data.cipher);
2969 channel->mode_data.cipher = NULL;
2970 channel->mode_data.key_len = 0;
2973 /* Generate new cipher and key for the channel */
2975 /* XXX Duplicated code, make own function for this!! */
2977 /* Delete old cipher and allocate default one */
2978 silc_cipher_free(channel->channel_key);
2979 if (!channel->cipher)
2980 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
2982 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
2983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2984 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2989 /* Re-generate channel key */
2990 silc_server_create_channel_key(server, channel, 0);
2992 /* Encode channel key payload to be distributed on the channel */
2994 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2995 strlen(channel->channel_key->
2997 channel->channel_key->cipher->name,
2998 channel->key_len / 8, channel->key);
3000 /* If we are normal server then we will send it to our router. If we
3001 are router we will send it to all local servers that has clients on
3003 if (server->server_type == SILC_SERVER) {
3004 if (!server->standalone)
3005 silc_server_packet_send(server,
3006 cmd->server->router->connection,
3007 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3013 /* Send to locally connected clients on the channel */
3014 silc_server_packet_send_local_channel(server, channel,
3015 SILC_PACKET_CHANNEL_KEY, 0,
3016 packet->data, packet->len, FALSE);
3017 silc_buffer_free(packet);
3021 /* Finally, set the mode */
3022 channel->mode = mode_mask;
3024 /* Send CMODE_CHANGE notify */
3025 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3026 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3027 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
3028 cidp->data, cidp->len,
3031 /* Set CMODE notify type to network */
3032 if (!server->standalone)
3033 silc_server_send_notify_cmode(server, server->router->connection,
3034 server->server_type == SILC_ROUTER ?
3035 TRUE : FALSE, channel,
3036 mode_mask, client->id, SILC_ID_CLIENT_LEN);
3038 /* Send command reply to sender */
3039 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3040 SILC_STATUS_OK, 0, 1,
3042 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3043 packet->data, packet->len, FALSE);
3045 silc_buffer_free(packet);
3046 silc_free(channel_id);
3050 silc_server_command_free(cmd);
3053 /* Server side of CUMODE command. Changes client's mode on a channel. */
3055 SILC_SERVER_CMD_FUNC(cumode)
3057 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3058 SilcServer server = cmd->server;
3059 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3060 SilcChannelID *channel_id;
3061 SilcClientID *client_id;
3062 SilcChannelEntry channel;
3063 SilcClientEntry target_client;
3064 SilcChannelClientEntry chl;
3065 SilcBuffer packet, idp;
3066 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3067 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3070 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3072 /* Get Channel ID */
3073 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3075 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3076 SILC_STATUS_ERR_NO_CHANNEL_ID);
3079 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3082 SILC_STATUS_ERR_NO_CHANNEL_ID);
3086 /* Get channel entry */
3087 channel = silc_idlist_find_channel_by_id(server->local_list,
3090 channel = silc_idlist_find_channel_by_id(server->global_list,
3093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3094 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3099 /* Check whether sender is on the channel */
3100 if (!silc_server_client_on_channel(client, channel)) {
3101 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3102 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3106 /* Check that client has rights to change other's rights */
3107 silc_list_start(channel->user_list);
3108 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3109 if (chl->client == client) {
3110 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3111 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3112 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3113 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3117 sender_mask = chl->mode;
3122 /* Get the target client's channel mode mask */
3123 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3125 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3126 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3129 SILC_GET32_MSB(target_mask, tmp_mask);
3131 /* Get target Client ID */
3132 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3134 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3135 SILC_STATUS_ERR_NO_CLIENT_ID);
3138 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3140 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3141 SILC_STATUS_ERR_NO_CLIENT_ID);
3145 /* Get target client's entry */
3146 target_client = silc_idlist_find_client_by_id(server->local_list,
3148 if (!target_client) {
3149 target_client = silc_idlist_find_client_by_id(server->global_list,
3153 /* Check whether target client is on the channel */
3154 if (!silc_server_client_on_channel(target_client, channel)) {
3155 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3156 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3160 /* Get entry to the channel user list */
3161 silc_list_start(channel->user_list);
3162 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3163 if (chl->client == target_client)
3170 /* If the target client is founder, no one else can change their mode
3172 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3173 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3174 SILC_STATUS_ERR_NOT_YOU);
3178 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3179 /* Cannot promote anyone to channel founder */
3180 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3181 SILC_STATUS_ERR_NOT_YOU);
3184 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3185 if (target_client == client) {
3186 /* Remove channel founder rights from itself */
3187 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3190 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3191 SILC_STATUS_ERR_NOT_YOU);
3197 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3198 /* Promote to operator */
3199 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3200 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3204 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3205 /* Demote to normal user */
3206 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3211 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3213 /* Send notify to channel, notify only if mode was actually changed. */
3215 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3216 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3217 idp->data, idp->len,
3221 /* Set CUMODE notify type to network */
3222 if (!server->standalone)
3223 silc_server_send_notify_cumode(server, server->router->connection,
3224 server->server_type == SILC_ROUTER ?
3225 TRUE : FALSE, channel,
3226 target_mask, client->id,
3229 SILC_ID_CLIENT_LEN);
3232 /* Send command reply to sender */
3233 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3234 SILC_STATUS_OK, 0, 2,
3236 3, tmp_id, tmp_len);
3237 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3238 packet->data, packet->len, FALSE);
3240 silc_buffer_free(packet);
3241 silc_free(channel_id);
3242 silc_free(client_id);
3243 silc_buffer_free(idp);
3246 silc_server_command_free(cmd);
3249 /* Server side of KICK command. Kicks client out of channel. */
3251 SILC_SERVER_CMD_FUNC(kick)
3253 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3254 SilcServer server = cmd->server;
3255 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3256 SilcClientEntry target_client;
3257 SilcChannelID *channel_id;
3258 SilcClientID *client_id;
3259 SilcChannelEntry channel;
3260 SilcChannelClientEntry chl;
3262 unsigned int tmp_len;
3263 unsigned char *tmp, *comment;
3265 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3267 /* Get Channel ID */
3268 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3271 SILC_STATUS_ERR_NO_CHANNEL_ID);
3274 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3277 SILC_STATUS_ERR_NO_CHANNEL_ID);
3281 /* Get channel entry */
3282 channel = silc_idlist_find_channel_by_id(server->local_list,
3285 channel = silc_idlist_find_channel_by_id(server->local_list,
3288 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3289 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3294 /* Check whether sender is on the channel */
3295 if (!silc_server_client_on_channel(client, channel)) {
3296 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3297 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3301 /* Check that the kicker is channel operator or channel founder */
3302 silc_list_start(channel->user_list);
3303 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3304 if (chl->client == client) {
3305 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3307 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3314 /* Get target Client ID */
3315 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3318 SILC_STATUS_ERR_NO_CLIENT_ID);
3321 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3323 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3324 SILC_STATUS_ERR_NO_CLIENT_ID);
3328 /* Get target client's entry */
3329 target_client = silc_idlist_find_client_by_id(server->local_list,
3331 if (!target_client) {
3332 target_client = silc_idlist_find_client_by_id(server->global_list,
3336 /* Check that the target client is not channel founder. Channel founder
3337 cannot be kicked from the channel. */
3338 silc_list_start(channel->user_list);
3339 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3340 if (chl->client == target_client) {
3341 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3343 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3350 /* Check whether target client is on the channel */
3351 if (!silc_server_client_on_channel(target_client, channel)) {
3352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3353 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3359 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3363 /* Send command reply to sender */
3364 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3367 /* Send KICKED notify to local clients on the channel */
3368 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3369 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3370 SILC_NOTIFY_TYPE_KICKED,
3372 idp->data, idp->len,
3373 comment, comment ? strlen(comment) : 0);
3374 silc_buffer_free(idp);
3376 /* Remove the client from the channel. If the channel does not exist
3377 after removing the client then the client kicked itself off the channel
3378 and we don't have to send anything after that. */
3379 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3380 target_client, FALSE))
3383 /* Send KICKED notify to primary route */
3384 if (!server->standalone)
3385 silc_server_send_notify_kicked(server, server->router->connection,
3386 server->server_type == SILC_ROUTER ?
3387 TRUE : FALSE, channel,
3388 target_client->id, SILC_ID_CLIENT_LEN,
3391 /* Re-generate channel key */
3392 silc_server_create_channel_key(server, channel, 0);
3394 /* Send the channel key to the channel. The key of course is not sent
3395 to the client who was kicked off the channel. */
3396 silc_server_send_channel_key(server, target_client->connection, channel,
3397 server->server_type == SILC_ROUTER ?
3398 FALSE : !server->standalone);
3401 silc_server_command_free(cmd);
3404 /* Server side of OPER command. Client uses this comand to obtain server
3405 operator privileges to this server/router. */
3407 SILC_SERVER_CMD_FUNC(oper)
3409 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3410 SilcServer server = cmd->server;
3411 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3412 unsigned char *username, *auth;
3413 unsigned int tmp_len;
3414 SilcServerConfigSectionAdminConnection *admin;
3415 SilcIDListData idata = (SilcIDListData)client;
3417 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
3419 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3422 /* Get the username */
3423 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3426 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3430 /* Get the admin configuration */
3431 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3432 username, client->nickname);
3434 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3435 username, client->nickname);
3437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3438 SILC_STATUS_ERR_AUTH_FAILED);
3443 /* Get the authentication payload */
3444 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3446 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3447 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3451 /* Verify the authentication data */
3452 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3453 admin->auth_data, admin->auth_data_len,
3454 idata->hash, client->id, SILC_ID_CLIENT)) {
3455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3456 SILC_STATUS_ERR_AUTH_FAILED);
3460 /* Client is now server operator */
3461 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3463 /* Send reply to the sender */
3464 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3468 silc_server_command_free(cmd);
3471 /* Server side of SILCOPER command. Client uses this comand to obtain router
3472 operator privileges to this router. */
3474 SILC_SERVER_CMD_FUNC(silcoper)
3476 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3477 SilcServer server = cmd->server;
3478 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3479 unsigned char *username, *auth;
3480 unsigned int tmp_len;
3481 SilcServerConfigSectionAdminConnection *admin;
3482 SilcIDListData idata = (SilcIDListData)client;
3484 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
3486 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3489 /* Get the username */
3490 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3492 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3493 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3497 /* Get the admin configuration */
3498 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3499 username, client->nickname);
3501 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3502 username, client->nickname);
3504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3505 SILC_STATUS_ERR_AUTH_FAILED);
3510 /* Get the authentication payload */
3511 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3513 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3514 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3518 /* Verify the authentication data */
3519 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3520 admin->auth_data, admin->auth_data_len,
3521 idata->hash, client->id, SILC_ID_CLIENT)) {
3522 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3523 SILC_STATUS_ERR_AUTH_FAILED);
3527 /* Client is now router operator */
3528 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
3530 /* Send reply to the sender */
3531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3535 silc_server_command_free(cmd);
3538 /* Server side command of CONNECT. Connects us to the specified remote
3539 server or router. */
3541 SILC_SERVER_CMD_FUNC(connect)
3543 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3544 SilcServer server = cmd->server;
3545 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3546 unsigned char *tmp, *host;
3547 unsigned int tmp_len;
3548 unsigned int port = SILC_PORT;
3550 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
3552 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3555 /* Check whether client has the permissions. */
3556 if (client->mode == SILC_UMODE_NONE) {
3557 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3558 SILC_STATUS_ERR_NO_SERVER_PRIV);
3562 if (server->server_type == SILC_ROUTER &&
3563 client->mode & SILC_UMODE_SERVER_OPERATOR) {
3564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3565 SILC_STATUS_ERR_NO_ROUTER_PRIV);
3569 /* Get the remote server */
3570 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3573 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3578 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3580 SILC_GET32_MSB(port, tmp);
3582 /* Create the connection. It is done with timeout and is async. */
3583 silc_server_create_connection(server, host, port);
3585 /* Send reply to the sender */
3586 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3590 silc_server_command_free(cmd);
3593 SILC_SERVER_CMD_FUNC(restart)
3597 /* Server side command of CLOSE. Closes connection to a specified server. */
3599 SILC_SERVER_CMD_FUNC(close)
3601 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3602 SilcServer server = cmd->server;
3603 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3604 SilcServerEntry server_entry;
3605 SilcSocketConnection sock;
3607 unsigned int tmp_len;
3608 unsigned char *name;
3609 unsigned int port = SILC_PORT;
3611 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3613 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3616 /* Check whether client has the permissions. */
3617 if (client->mode == SILC_UMODE_NONE) {
3618 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3619 SILC_STATUS_ERR_NO_SERVER_PRIV);
3623 /* Get the remote server */
3624 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3626 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3627 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3632 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3634 SILC_GET32_MSB(port, tmp);
3636 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3638 if (!server_entry) {
3639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3640 SILC_STATUS_ERR_NO_SERVER_ID);
3644 /* Send reply to the sender */
3645 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3648 /* Close the connection to the server */
3649 sock = (SilcSocketConnection)server_entry->connection;
3650 silc_server_free_sock_user_data(server, sock);
3651 silc_server_close_connection(server, sock);
3654 silc_server_command_free(cmd);
3657 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3658 active connections. */
3660 SILC_SERVER_CMD_FUNC(shutdown)
3662 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3663 SilcServer server = cmd->server;
3664 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3666 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3668 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3671 /* Check whether client has the permission. */
3672 if (client->mode == SILC_UMODE_NONE) {
3673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3674 SILC_STATUS_ERR_NO_SERVER_PRIV);
3678 /* Send reply to the sender */
3679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3682 /* Then, gracefully, or not, bring the server down. */
3683 silc_server_stop(server);
3687 silc_server_command_free(cmd);
3690 /* Server side command of LEAVE. Removes client from a channel. */
3692 SILC_SERVER_CMD_FUNC(leave)
3694 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3695 SilcServer server = cmd->server;
3696 SilcSocketConnection sock = cmd->sock;
3697 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3699 SilcChannelEntry channel;
3701 unsigned int i, len;
3704 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3706 /* Get Channel ID */
3707 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3709 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3710 SILC_STATUS_ERR_NO_CHANNEL_ID);
3713 id = silc_id_payload_parse_id(tmp, len);
3715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3716 SILC_STATUS_ERR_NO_CHANNEL_ID);
3720 /* Get channel entry */
3721 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3723 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3725 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3726 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3731 /* Check whether this client is on the channel */
3732 if (!silc_server_client_on_channel(id_entry, channel)) {
3733 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3734 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3738 /* Notify routers that they should remove this client from their list
3739 of clients on the channel. Send LEAVE notify type. */
3740 if (!server->standalone)
3741 silc_server_send_notify_leave(server, server->router->connection,
3742 server->server_type == SILC_ROUTER ?
3743 TRUE : FALSE, channel, id_entry->id,
3744 SILC_ID_CLIENT_LEN);
3746 /* Remove client from channel */
3747 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3749 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3752 /* If the channel does not exist anymore we won't send anything */
3756 /* Re-generate channel key */
3757 silc_server_create_channel_key(server, channel, 0);
3759 /* Encode channel key payload to be distributed on the channel */
3761 silc_channel_key_payload_encode(len, tmp,
3762 strlen(channel->channel_key->cipher->name),
3763 channel->channel_key->cipher->name,
3764 channel->key_len / 8, channel->key);
3766 /* If we are normal server then we will send it to our router. If we
3767 are router we will send it to all local servers that has clients on
3769 if (server->server_type == SILC_SERVER) {
3770 if (!server->standalone)
3771 silc_server_packet_send(server,
3772 cmd->server->router->connection,
3773 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3774 packet->len, FALSE);
3779 /* Send to locally connected clients on the channel */
3780 silc_server_packet_send_local_channel(server, channel,
3781 SILC_PACKET_CHANNEL_KEY, 0,
3782 packet->data, packet->len, FALSE);
3784 silc_buffer_free(packet);
3788 silc_server_command_free(cmd);
3791 /* Server side of command USERS. Resolves clients and their USERS currently
3792 joined on the requested channel. The list of Client ID's and their modes
3793 on the channel is sent back. */
3795 SILC_SERVER_CMD_FUNC(users)
3797 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3798 SilcServer server = cmd->server;
3799 SilcChannelEntry channel;
3802 unsigned char *channel_id;
3803 unsigned int channel_id_len;
3804 SilcBuffer client_id_list;
3805 SilcBuffer client_mode_list;
3806 unsigned char lc[4];
3807 unsigned int list_count = 0;
3808 unsigned short ident = silc_command_get_ident(cmd->payload);
3810 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3812 /* Get Channel ID */
3813 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3816 SILC_STATUS_ERR_NO_CHANNEL_ID);
3819 id = silc_id_payload_parse_id(channel_id, channel_id_len);
3821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3822 SILC_STATUS_ERR_NO_CHANNEL_ID);
3826 /* If we are server and we don't know about this channel we will send
3827 the command to our router. If we know about the channel then we also
3828 have the list of users already. */
3829 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3831 if (server->server_type == SILC_SERVER && !server->standalone &&
3835 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3836 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3838 /* Send USERS command */
3839 silc_server_packet_send(server, server->router->connection,
3840 SILC_PACKET_COMMAND, cmd->packet->flags,
3841 tmpbuf->data, tmpbuf->len, TRUE);
3843 /* Reprocess this packet after received reply */
3844 silc_server_command_pending(server, SILC_COMMAND_USERS,
3845 silc_command_get_ident(cmd->payload),
3846 silc_server_command_destructor,
3847 silc_server_command_users,
3848 silc_server_command_dup(cmd));
3849 cmd->pending = TRUE;
3850 silc_command_set_ident(cmd->payload, ident);
3852 silc_buffer_free(tmpbuf);
3857 /* We are router and we will check the global list as well. */
3858 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3860 /* Channel really does not exist */
3861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3862 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3867 /* Get the users list */
3868 silc_server_get_users_on_channel(server, channel, &client_id_list,
3869 &client_mode_list, &list_count);
3872 SILC_PUT32_MSB(list_count, lc);
3875 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3876 SILC_STATUS_OK, 0, 4,
3877 2, channel_id, channel_id_len,
3879 4, client_id_list->data,
3880 client_id_list->len,
3881 5, client_mode_list->data,
3882 client_mode_list->len);
3883 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3884 packet->data, packet->len, FALSE);
3886 silc_buffer_free(packet);
3887 silc_buffer_free(client_id_list);
3888 silc_buffer_free(client_mode_list);
3892 silc_server_command_free(cmd);