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, tmp_len2;
2026 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2028 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2031 /* KILL command works only on router */
2032 if (server->server_type != SILC_ROUTER) {
2033 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2034 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2038 /* Check whether client has the permissions. */
2039 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2040 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2041 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2045 /* Get the client ID */
2046 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2048 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2049 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2052 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2054 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2055 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2059 /* Get the client entry */
2060 remote_client = silc_idlist_find_client_by_id(server->local_list,
2062 if (!remote_client) {
2063 remote_client = silc_idlist_find_client_by_id(server->global_list,
2065 if (!remote_client) {
2066 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2067 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2073 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2077 /* Send reply to the sender */
2078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2081 /* Send the KILL notify packets. First send it to the channel, then
2082 to our primary router and then directly to the client who is being
2083 killed right now. */
2085 /* Send KILLED notify to the channels. It is not sent to the client
2086 as it will be sent differently destined directly to the client and not
2088 silc_server_send_notify_on_channels(server, remote_client,
2089 remote_client, SILC_NOTIFY_TYPE_KILLED,
2092 comment, comment ? tmp_len2 : 0);
2094 /* Send KILLED notify to primary route */
2095 if (!server->standalone)
2096 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2097 remote_client->id, SILC_ID_CLIENT_LEN,
2100 /* Send KILLED notify to the client directly */
2101 silc_server_send_notify_killed(server, remote_client->connection ?
2102 remote_client->connection :
2103 remote_client->router->connection, FALSE,
2104 remote_client->id, SILC_ID_CLIENT_LEN,
2107 /* Remove the client from all channels. This generates new keys to the
2108 channels as well. */
2109 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2112 /* Remove the client entry, If it is locally connected then we will also
2113 disconnect the client here */
2114 if (remote_client->data.registered && remote_client->connection) {
2115 /* Remove locally conneted client */
2116 SilcSocketConnection sock = remote_client->connection;
2117 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2118 silc_server_close_connection(server, sock);
2120 /* Remove remote client */
2121 if (!silc_idlist_del_client(server->global_list, remote_client))
2122 silc_idlist_del_client(server->local_list, remote_client);
2126 silc_server_command_free(cmd);
2129 /* Server side of command INFO. This sends information about us to
2130 the client. If client requested specific server we will send the
2131 command to that server. */
2133 SILC_SERVER_CMD_FUNC(info)
2135 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2136 SilcServer server = cmd->server;
2137 SilcBuffer packet, idp;
2138 char info_string[256], *dest_server;
2140 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
2142 /* Get server name */
2143 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2145 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2146 SILC_STATUS_ERR_NO_SUCH_SERVER);
2150 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2151 /* Send our reply */
2152 memset(info_string, 0, sizeof(info_string));
2153 snprintf(info_string, sizeof(info_string),
2154 "location: %s server: %s admin: %s <%s>",
2155 server->config->admin_info->location,
2156 server->config->admin_info->server_type,
2157 server->config->admin_info->admin_name,
2158 server->config->admin_info->admin_email);
2160 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2162 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2163 SILC_STATUS_OK, 0, 2,
2164 2, idp->data, idp->len,
2166 strlen(info_string));
2167 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2168 packet->data, packet->len, FALSE);
2170 silc_buffer_free(packet);
2171 silc_buffer_free(idp);
2173 /* Send this command to the requested server */
2175 if (server->server_type == SILC_SERVER && !server->standalone) {
2179 if (server->server_type == SILC_ROUTER) {
2185 silc_server_command_free(cmd);
2188 /* Server side of command PING. This just replies to the ping. */
2190 SILC_SERVER_CMD_FUNC(ping)
2192 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2193 SilcServer server = cmd->server;
2198 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2201 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2203 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2204 SILC_STATUS_ERR_NO_SERVER_ID);
2207 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2211 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2212 /* Send our reply */
2213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2216 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2217 SILC_STATUS_ERR_NO_SUCH_SERVER);
2224 silc_server_command_free(cmd);
2227 /* Internal routine to join channel. The channel sent to this function
2228 has been either created or resolved from ID lists. This joins the sent
2229 client to the channel. */
2231 static void silc_server_command_join_channel(SilcServer server,
2232 SilcServerCommandContext cmd,
2233 SilcChannelEntry channel,
2234 SilcClientID *client_id,
2238 SilcSocketConnection sock = cmd->sock;
2240 unsigned int tmp_len, user_count;
2241 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2242 SilcClientEntry client;
2243 SilcChannelClientEntry chl;
2244 SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
2245 unsigned short ident = silc_command_get_ident(cmd->payload);
2247 SILC_LOG_DEBUG(("Start"));
2252 /* Get passphrase */
2253 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2255 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2256 memcpy(passphrase, tmp, tmp_len);
2260 * Check channel modes
2263 /* Check invite list if channel is invite-only channel */
2264 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2265 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2266 /* Invite list is specified. Check whether client is invited in the
2267 list. If not, then check whether it has been invited otherwise. */
2270 /* XXX client must be invited to be able to join the channel */
2274 /* Check ban list if set */
2275 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2279 /* Check the channel passphrase if set. */
2280 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2281 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
2282 strlen(channel->mode_data.passphrase))) {
2283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2284 SILC_STATUS_ERR_BAD_PASSWORD);
2289 /* Check user count limit if set. */
2290 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2291 if (silc_list_count(channel->user_list) + 1 >
2292 channel->mode_data.user_limit) {
2293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2294 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2300 * Client is allowed to join to the channel. Make it happen.
2303 /* Get the client entry */
2304 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2305 client = (SilcClientEntry)sock->user_data;
2307 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2310 /* XXX actually this is useless since router finds always cell's
2311 local clients from its local lists. */
2312 client = silc_idlist_find_client_by_id(server->global_list, client_id,
2319 /* Check whether the client already is on the channel */
2320 if (silc_server_client_on_channel(client, channel)) {
2321 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2322 SILC_STATUS_ERR_USER_ON_CHANNEL);
2326 /* Generate new channel key as protocol dictates */
2327 if ((!created && silc_list_count(channel->user_list) > 0) ||
2328 !channel->channel_key)
2329 silc_server_create_channel_key(server, channel, 0);
2331 /* Send the channel key. This is broadcasted to the channel but is not
2332 sent to the client who is joining to the channel. */
2333 silc_server_send_channel_key(server, NULL, channel,
2334 server->server_type == SILC_ROUTER ?
2335 FALSE : !server->standalone);
2337 /* Join the client to the channel by adding it to channel's user list.
2338 Add also the channel to client entry's channels list for fast cross-
2340 chl = silc_calloc(1, sizeof(*chl));
2342 chl->client = client;
2343 chl->channel = channel;
2344 silc_list_add(channel->user_list, chl);
2345 silc_list_add(client->channels, chl);
2347 /* Get users on the channel */
2348 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2351 /* Encode Client ID Payload of the original client who wants to join */
2352 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2354 /* Encode command reply packet */
2355 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2356 SILC_PUT32_MSB(channel->mode, mode);
2357 SILC_PUT32_MSB(created, tmp2);
2358 SILC_PUT32_MSB(user_count, tmp3);
2359 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2360 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2361 strlen(channel->channel_key->
2363 channel->channel_key->cipher->name,
2364 channel->key_len / 8, channel->key);
2366 if (!channel->topic) {
2368 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2369 SILC_STATUS_OK, ident, 9,
2370 2, channel->channel_name,
2371 strlen(channel->channel_name),
2372 3, chidp->data, chidp->len,
2373 4, clidp->data, clidp->len,
2376 7, keyp->data, keyp->len,
2378 13, user_list->data, user_list->len,
2379 14, mode_list->data,
2383 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2384 SILC_STATUS_OK, ident, 10,
2385 2, channel->channel_name,
2386 strlen(channel->channel_name),
2387 3, chidp->data, chidp->len,
2388 4, clidp->data, clidp->len,
2391 7, keyp->data, keyp->len,
2393 strlen(channel->topic),
2395 13, user_list->data, user_list->len,
2396 14, mode_list->data,
2400 /* Send command reply */
2401 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2402 reply->data, reply->len, FALSE);
2404 if (!cmd->pending) {
2405 /* Send JOIN notify to locally connected clients on the channel */
2406 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2407 SILC_NOTIFY_TYPE_JOIN, 2,
2408 clidp->data, clidp->len,
2409 chidp->data, chidp->len);
2411 /* Send JOIN notify packet to our primary router */
2412 if (!server->standalone)
2413 silc_server_send_notify_join(server, server->router->connection,
2414 server->server_type == SILC_ROUTER ?
2415 TRUE : FALSE, channel, client->id,
2416 SILC_ID_CLIENT_LEN);
2419 silc_buffer_free(reply);
2420 silc_buffer_free(clidp);
2421 silc_buffer_free(chidp);
2422 silc_buffer_free(keyp);
2423 silc_buffer_free(user_list);
2424 silc_buffer_free(mode_list);
2428 silc_free(passphrase);
2431 /* Server side of command JOIN. Joins client into requested channel. If
2432 the channel does not exist it will be created. */
2434 SILC_SERVER_CMD_FUNC(join)
2436 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2437 SilcServer server = cmd->server;
2439 char *tmp, *channel_name = NULL, *cipher, *hmac;
2440 SilcChannelEntry channel;
2441 unsigned int umode = 0;
2442 int created = FALSE;
2443 SilcClientID *client_id;
2445 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2447 /* Get channel name */
2448 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2451 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2456 if (strlen(channel_name) > 256)
2457 channel_name[255] = '\0';
2459 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2461 SILC_STATUS_ERR_BAD_CHANNEL);
2462 silc_free(channel_name);
2466 /* Get Client ID of the client who is joining to the channel */
2467 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2470 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2473 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2475 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2476 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2480 /* Get cipher and hmac name */
2481 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2482 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2484 /* See if the channel exists */
2485 channel = silc_idlist_find_channel_by_name(server->local_list,
2486 channel_name, NULL);
2488 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2489 /* If this is coming from client the Client ID in the command packet must
2490 be same as the client's ID. */
2491 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2492 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2493 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2494 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2495 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2501 /* Channel not found */
2503 /* If we are standalone server we don't have a router, we just create
2504 the channel by ourselves. */
2505 if (server->standalone) {
2506 channel = silc_server_create_new_channel(server, server->id, cipher,
2507 hmac, channel_name, TRUE);
2508 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2513 /* The channel does not exist on our server. If we are normal server
2514 we will send JOIN command to our router which will handle the
2515 joining procedure (either creates the channel if it doesn't exist
2516 or joins the client to it). */
2517 if (server->server_type == SILC_SERVER) {
2519 unsigned short old_ident;
2521 old_ident = silc_command_get_ident(cmd->payload);
2522 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2523 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2525 /* Send JOIN command to our router */
2526 silc_server_packet_send(server, (SilcSocketConnection)
2527 server->router->connection,
2528 SILC_PACKET_COMMAND, cmd->packet->flags,
2529 tmpbuf->data, tmpbuf->len, TRUE);
2531 /* Reprocess this packet after received reply from router */
2532 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2533 silc_command_get_ident(cmd->payload),
2534 silc_server_command_destructor,
2535 silc_server_command_join,
2536 silc_server_command_dup(cmd));
2537 cmd->pending = TRUE;
2541 /* We are router and the channel does not seem exist so we will check
2542 our global list as well for the channel. */
2543 channel = silc_idlist_find_channel_by_name(server->global_list,
2544 channel_name, NULL);
2546 /* Channel really does not exist, create it */
2547 channel = silc_server_create_new_channel(server, server->id, cipher,
2548 hmac, channel_name, TRUE);
2549 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2556 /* Channel not found */
2558 /* If the command came from router and/or we are normal server then
2559 something went wrong with the joining as the channel was not found.
2560 We can't do anything else but ignore this. */
2561 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2562 server->server_type == SILC_SERVER)
2565 /* We are router and the channel does not seem exist so we will check
2566 our global list as well for the channel. */
2567 channel = silc_idlist_find_channel_by_name(server->global_list,
2568 channel_name, NULL);
2570 /* Channel really does not exist, create it */
2571 channel = silc_server_create_new_channel(server, server->id, cipher,
2572 hmac, channel_name, TRUE);
2573 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2579 /* If the channel does not have global users and is also empty it means the
2580 channel was created globally (by our router) and the client will be the
2581 channel founder and operator. */
2582 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2583 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2584 created = TRUE; /* Created globally by our router */
2587 /* Join to the channel */
2588 silc_server_command_join_channel(server, cmd, channel, client_id,
2591 silc_free(client_id);
2594 silc_server_command_free(cmd);
2597 /* Server side of command MOTD. Sends server's current "message of the
2598 day" to the client. */
2600 SILC_SERVER_CMD_FUNC(motd)
2602 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2603 SilcServer server = cmd->server;
2607 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2609 /* XXX show currently only our motd */
2611 if (server->config && server->config->motd &&
2612 server->config->motd->motd_file) {
2615 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2620 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2626 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2631 silc_server_command_free(cmd);
2634 SILC_SERVER_CMD_FUNC(umode)
2638 /* Checks that client has rights to add or remove channel modes. If any
2639 of the checks fails FALSE is returned. */
2641 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2642 SilcChannelClientEntry client,
2645 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2646 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2648 /* Check whether has rights to change anything */
2649 if (!is_op && !is_fo)
2652 /* Check whether has rights to change everything */
2656 /* We know that client is channel operator, check that they are not
2657 changing anything that requires channel founder rights. Rest of the
2658 modes are available automatically for channel operator. */
2660 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2661 if (is_op && !is_fo)
2664 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2665 if (is_op && !is_fo)
2670 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2671 if (is_op && !is_fo)
2674 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2675 if (is_op && !is_fo)
2680 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2681 if (is_op && !is_fo)
2684 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2685 if (is_op && !is_fo)
2693 /* Server side command of CMODE. Changes channel mode */
2695 SILC_SERVER_CMD_FUNC(cmode)
2697 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2698 SilcServer server = cmd->server;
2699 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2700 SilcChannelID *channel_id;
2701 SilcChannelEntry channel;
2702 SilcChannelClientEntry chl;
2703 SilcBuffer packet, cidp;
2704 unsigned char *tmp, *tmp_id, *tmp_mask;
2705 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2707 SILC_LOG_DEBUG(("Start"));
2709 argc = silc_argument_get_arg_num(cmd->args);
2711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2712 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2716 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2717 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2721 /* Get Channel ID */
2722 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2724 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2725 SILC_STATUS_ERR_NO_CHANNEL_ID);
2728 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2730 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2731 SILC_STATUS_ERR_NO_CHANNEL_ID);
2735 /* Get the channel mode mask */
2736 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2739 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2742 SILC_GET32_MSB(mode_mask, tmp_mask);
2744 /* Get channel entry */
2745 channel = silc_idlist_find_channel_by_id(server->local_list,
2748 channel = silc_idlist_find_channel_by_id(server->global_list,
2751 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2752 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2757 /* Check whether this client is on the channel */
2758 if (!silc_server_client_on_channel(client, channel)) {
2759 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2760 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2764 /* Get entry to the channel user list */
2765 silc_list_start(channel->user_list);
2766 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2767 if (chl->client == client)
2770 /* Check that client has rights to change any requested channel modes */
2771 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2773 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2778 * Check the modes. Modes that requires nothing special operation are
2782 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2783 /* Channel uses private keys to protect traffic. Client(s) has set the
2784 key locally they want to use, server does not know that key. */
2785 /* Nothing interesting to do here now */
2787 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2788 /* The mode is removed and we need to generate and distribute
2789 new channel key. Clients are not using private channel keys
2790 anymore after this. */
2792 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2795 /* Re-generate channel key */
2796 silc_server_create_channel_key(server, channel, 0);
2798 /* Encode channel key payload to be distributed on the channel */
2800 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2801 strlen(channel->channel_key->
2803 channel->channel_key->cipher->name,
2804 channel->key_len / 8, channel->key);
2806 /* If we are normal server then we will send it to our router. If we
2807 are router we will send it to all local servers that has clients on
2809 if (server->server_type == SILC_SERVER) {
2810 if (!server->standalone)
2811 silc_server_packet_send(server,
2812 cmd->server->router->connection,
2813 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2819 /* Send to locally connected clients on the channel */
2820 silc_server_packet_send_local_channel(server, channel,
2821 SILC_PACKET_CHANNEL_KEY, 0,
2822 packet->data, packet->len, FALSE);
2823 silc_buffer_free(packet);
2827 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2828 /* User limit is set on channel */
2829 unsigned int user_limit;
2831 /* Get user limit */
2832 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2834 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2836 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2840 SILC_GET32_MSB(user_limit, tmp);
2841 channel->mode_data.user_limit = user_limit;
2844 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2845 /* User limit mode is unset. Remove user limit */
2846 channel->mode_data.user_limit = 0;
2849 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2850 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2851 /* Passphrase has been set to channel */
2853 /* Get the passphrase */
2854 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2856 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2857 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2861 /* Save the passphrase */
2862 channel->mode_data.passphrase = strdup(tmp);
2865 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2866 /* Passphrase mode is unset. remove the passphrase */
2867 if (channel->mode_data.passphrase) {
2868 silc_free(channel->mode_data.passphrase);
2869 channel->mode_data.passphrase = NULL;
2874 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2875 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2876 /* Ban list is specified for channel */
2879 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2881 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2882 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2886 /* XXX check that channel founder is not banned */
2888 /* Save the ban list */
2889 channel->mode_data.ban_list = strdup(tmp);
2892 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2893 /* Ban mode is unset. Remove the entire ban list */
2894 if (channel->mode_data.ban_list) {
2895 silc_free(channel->mode_data.ban_list);
2896 channel->mode_data.ban_list = NULL;
2901 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2902 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2903 /* Invite list is specified for channel */
2905 /* Get invite list */
2906 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2908 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2909 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2913 /* Save the invite linst */
2914 channel->mode_data.invite_list = strdup(tmp);
2917 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2918 /* Invite list mode is unset. Remove the entire invite list */
2919 if (channel->mode_data.invite_list) {
2920 silc_free(channel->mode_data.invite_list);
2921 channel->mode_data.invite_list = NULL;
2926 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2927 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2928 /* Cipher to use protect the traffic */
2929 unsigned int key_len;
2932 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2934 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2935 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2939 /* XXX Duplicated code, make own function for this!! */
2941 /* Delete old cipher and allocate the new one */
2942 silc_cipher_free(channel->channel_key);
2943 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
2944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2945 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2948 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
2950 /* Re-generate channel key */
2951 silc_server_create_channel_key(server, channel, key_len);
2953 /* Encode channel key payload to be distributed on the channel */
2955 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2956 strlen(channel->channel_key->
2958 channel->channel_key->cipher->name,
2959 channel->key_len / 8, channel->key);
2961 /* If we are normal server then we will send it to our router. If we
2962 are router we will send it to all local servers that has clients on
2964 if (server->server_type == SILC_SERVER) {
2965 if (!server->standalone)
2966 silc_server_packet_send(server,
2967 cmd->server->router->connection,
2968 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2974 /* Send to locally connected clients on the channel */
2975 silc_server_packet_send_local_channel(server, channel,
2976 SILC_PACKET_CHANNEL_KEY, 0,
2977 packet->data, packet->len, FALSE);
2978 silc_buffer_free(packet);
2981 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2982 /* Cipher mode is unset. Remove the cipher and revert back to
2985 if (channel->mode_data.cipher) {
2986 silc_free(channel->mode_data.cipher);
2987 channel->mode_data.cipher = NULL;
2988 channel->mode_data.key_len = 0;
2991 /* Generate new cipher and key for the channel */
2993 /* XXX Duplicated code, make own function for this!! */
2995 /* Delete old cipher and allocate default one */
2996 silc_cipher_free(channel->channel_key);
2997 if (!channel->cipher)
2998 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
3000 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
3001 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3002 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3007 /* Re-generate channel key */
3008 silc_server_create_channel_key(server, channel, 0);
3010 /* Encode channel key payload to be distributed on the channel */
3012 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3013 strlen(channel->channel_key->
3015 channel->channel_key->cipher->name,
3016 channel->key_len / 8, channel->key);
3018 /* If we are normal server then we will send it to our router. If we
3019 are router we will send it to all local servers that has clients on
3021 if (server->server_type == SILC_SERVER) {
3022 if (!server->standalone)
3023 silc_server_packet_send(server,
3024 cmd->server->router->connection,
3025 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3031 /* Send to locally connected clients on the channel */
3032 silc_server_packet_send_local_channel(server, channel,
3033 SILC_PACKET_CHANNEL_KEY, 0,
3034 packet->data, packet->len, FALSE);
3035 silc_buffer_free(packet);
3039 /* Finally, set the mode */
3040 channel->mode = mode_mask;
3042 /* Send CMODE_CHANGE notify */
3043 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3044 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3045 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
3046 cidp->data, cidp->len,
3049 /* Set CMODE notify type to network */
3050 if (!server->standalone)
3051 silc_server_send_notify_cmode(server, server->router->connection,
3052 server->server_type == SILC_ROUTER ?
3053 TRUE : FALSE, channel,
3054 mode_mask, client->id, SILC_ID_CLIENT_LEN);
3056 /* Send command reply to sender */
3057 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3058 SILC_STATUS_OK, 0, 1,
3060 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3061 packet->data, packet->len, FALSE);
3063 silc_buffer_free(packet);
3064 silc_free(channel_id);
3068 silc_server_command_free(cmd);
3071 /* Server side of CUMODE command. Changes client's mode on a channel. */
3073 SILC_SERVER_CMD_FUNC(cumode)
3075 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3076 SilcServer server = cmd->server;
3077 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3078 SilcChannelID *channel_id;
3079 SilcClientID *client_id;
3080 SilcChannelEntry channel;
3081 SilcClientEntry target_client;
3082 SilcChannelClientEntry chl;
3083 SilcBuffer packet, idp;
3084 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3085 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3088 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3090 /* Get Channel ID */
3091 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3094 SILC_STATUS_ERR_NO_CHANNEL_ID);
3097 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3099 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3100 SILC_STATUS_ERR_NO_CHANNEL_ID);
3104 /* Get channel entry */
3105 channel = silc_idlist_find_channel_by_id(server->local_list,
3108 channel = silc_idlist_find_channel_by_id(server->global_list,
3111 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3112 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3117 /* Check whether sender is on the channel */
3118 if (!silc_server_client_on_channel(client, channel)) {
3119 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3120 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3124 /* Check that client has rights to change other's rights */
3125 silc_list_start(channel->user_list);
3126 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3127 if (chl->client == client) {
3128 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3129 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3131 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3135 sender_mask = chl->mode;
3140 /* Get the target client's channel mode mask */
3141 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3143 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3144 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3147 SILC_GET32_MSB(target_mask, tmp_mask);
3149 /* Get target Client ID */
3150 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3152 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3153 SILC_STATUS_ERR_NO_CLIENT_ID);
3156 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3158 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3159 SILC_STATUS_ERR_NO_CLIENT_ID);
3163 /* Get target client's entry */
3164 target_client = silc_idlist_find_client_by_id(server->local_list,
3166 if (!target_client) {
3167 target_client = silc_idlist_find_client_by_id(server->global_list,
3171 /* Check whether target client is on the channel */
3172 if (!silc_server_client_on_channel(target_client, channel)) {
3173 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3174 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3178 /* Get entry to the channel user list */
3179 silc_list_start(channel->user_list);
3180 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3181 if (chl->client == target_client)
3188 /* If the target client is founder, no one else can change their mode
3190 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3192 SILC_STATUS_ERR_NOT_YOU);
3196 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3197 /* Cannot promote anyone to channel founder */
3198 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3199 SILC_STATUS_ERR_NOT_YOU);
3202 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3203 if (target_client == client) {
3204 /* Remove channel founder rights from itself */
3205 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3209 SILC_STATUS_ERR_NOT_YOU);
3215 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3216 /* Promote to operator */
3217 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3218 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3222 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3223 /* Demote to normal user */
3224 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3229 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3231 /* Send notify to channel, notify only if mode was actually changed. */
3233 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3234 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3235 idp->data, idp->len,
3239 /* Set CUMODE notify type to network */
3240 if (!server->standalone)
3241 silc_server_send_notify_cumode(server, server->router->connection,
3242 server->server_type == SILC_ROUTER ?
3243 TRUE : FALSE, channel,
3244 target_mask, client->id,
3247 SILC_ID_CLIENT_LEN);
3250 /* Send command reply to sender */
3251 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3252 SILC_STATUS_OK, 0, 2,
3254 3, tmp_id, tmp_len);
3255 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3256 packet->data, packet->len, FALSE);
3258 silc_buffer_free(packet);
3259 silc_free(channel_id);
3260 silc_free(client_id);
3261 silc_buffer_free(idp);
3264 silc_server_command_free(cmd);
3267 /* Server side of KICK command. Kicks client out of channel. */
3269 SILC_SERVER_CMD_FUNC(kick)
3271 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3272 SilcServer server = cmd->server;
3273 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3274 SilcClientEntry target_client;
3275 SilcChannelID *channel_id;
3276 SilcClientID *client_id;
3277 SilcChannelEntry channel;
3278 SilcChannelClientEntry chl;
3280 unsigned int tmp_len;
3281 unsigned char *tmp, *comment;
3283 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3285 /* Get Channel ID */
3286 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3288 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3289 SILC_STATUS_ERR_NO_CHANNEL_ID);
3292 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3295 SILC_STATUS_ERR_NO_CHANNEL_ID);
3299 /* Get channel entry */
3300 channel = silc_idlist_find_channel_by_id(server->local_list,
3303 channel = silc_idlist_find_channel_by_id(server->local_list,
3306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3307 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3312 /* Check whether sender is on the channel */
3313 if (!silc_server_client_on_channel(client, channel)) {
3314 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3315 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3319 /* Check that the kicker is channel operator or channel founder */
3320 silc_list_start(channel->user_list);
3321 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3322 if (chl->client == client) {
3323 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3325 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3332 /* Get target Client ID */
3333 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3336 SILC_STATUS_ERR_NO_CLIENT_ID);
3339 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3342 SILC_STATUS_ERR_NO_CLIENT_ID);
3346 /* Get target client's entry */
3347 target_client = silc_idlist_find_client_by_id(server->local_list,
3349 if (!target_client) {
3350 target_client = silc_idlist_find_client_by_id(server->global_list,
3354 /* Check that the target client is not channel founder. Channel founder
3355 cannot be kicked from the channel. */
3356 silc_list_start(channel->user_list);
3357 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3358 if (chl->client == target_client) {
3359 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3360 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3361 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3368 /* Check whether target client is on the channel */
3369 if (!silc_server_client_on_channel(target_client, channel)) {
3370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3371 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3377 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3381 /* Send command reply to sender */
3382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3385 /* Send KICKED notify to local clients on the channel */
3386 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3387 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3388 SILC_NOTIFY_TYPE_KICKED,
3390 idp->data, idp->len,
3391 comment, comment ? strlen(comment) : 0);
3392 silc_buffer_free(idp);
3394 /* Remove the client from the channel. If the channel does not exist
3395 after removing the client then the client kicked itself off the channel
3396 and we don't have to send anything after that. */
3397 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3398 target_client, FALSE))
3401 /* Send KICKED notify to primary route */
3402 if (!server->standalone)
3403 silc_server_send_notify_kicked(server, server->router->connection,
3404 server->server_type == SILC_ROUTER ?
3405 TRUE : FALSE, channel,
3406 target_client->id, SILC_ID_CLIENT_LEN,
3409 /* Re-generate channel key */
3410 silc_server_create_channel_key(server, channel, 0);
3412 /* Send the channel key to the channel. The key of course is not sent
3413 to the client who was kicked off the channel. */
3414 silc_server_send_channel_key(server, target_client->connection, channel,
3415 server->server_type == SILC_ROUTER ?
3416 FALSE : !server->standalone);
3419 silc_server_command_free(cmd);
3422 /* Server side of OPER command. Client uses this comand to obtain server
3423 operator privileges to this server/router. */
3425 SILC_SERVER_CMD_FUNC(oper)
3427 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3428 SilcServer server = cmd->server;
3429 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3430 unsigned char *username, *auth;
3431 unsigned int tmp_len;
3432 SilcServerConfigSectionAdminConnection *admin;
3433 SilcIDListData idata = (SilcIDListData)client;
3435 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
3437 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3440 /* Get the username */
3441 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3444 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3448 /* Get the admin configuration */
3449 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3450 username, client->nickname);
3452 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3453 username, client->nickname);
3455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3456 SILC_STATUS_ERR_AUTH_FAILED);
3461 /* Get the authentication payload */
3462 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3464 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3465 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3469 /* Verify the authentication data */
3470 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3471 admin->auth_data, admin->auth_data_len,
3472 idata->hash, client->id, SILC_ID_CLIENT)) {
3473 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3474 SILC_STATUS_ERR_AUTH_FAILED);
3478 /* Client is now server operator */
3479 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3481 /* Send reply to the sender */
3482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3486 silc_server_command_free(cmd);
3489 /* Server side of SILCOPER command. Client uses this comand to obtain router
3490 operator privileges to this router. */
3492 SILC_SERVER_CMD_FUNC(silcoper)
3494 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3495 SilcServer server = cmd->server;
3496 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3497 unsigned char *username, *auth;
3498 unsigned int tmp_len;
3499 SilcServerConfigSectionAdminConnection *admin;
3500 SilcIDListData idata = (SilcIDListData)client;
3502 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
3504 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3507 /* Get the username */
3508 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3511 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3515 /* Get the admin configuration */
3516 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3517 username, client->nickname);
3519 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3520 username, client->nickname);
3522 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3523 SILC_STATUS_ERR_AUTH_FAILED);
3528 /* Get the authentication payload */
3529 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3532 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3536 /* Verify the authentication data */
3537 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3538 admin->auth_data, admin->auth_data_len,
3539 idata->hash, client->id, SILC_ID_CLIENT)) {
3540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3541 SILC_STATUS_ERR_AUTH_FAILED);
3545 /* Client is now router operator */
3546 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
3548 /* Send reply to the sender */
3549 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3553 silc_server_command_free(cmd);
3556 /* Server side command of CONNECT. Connects us to the specified remote
3557 server or router. */
3559 SILC_SERVER_CMD_FUNC(connect)
3561 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3562 SilcServer server = cmd->server;
3563 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3564 unsigned char *tmp, *host;
3565 unsigned int tmp_len;
3566 unsigned int port = SILC_PORT;
3568 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
3570 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3573 /* Check whether client has the permissions. */
3574 if (client->mode == SILC_UMODE_NONE) {
3575 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3576 SILC_STATUS_ERR_NO_SERVER_PRIV);
3580 if (server->server_type == SILC_ROUTER &&
3581 client->mode & SILC_UMODE_SERVER_OPERATOR) {
3582 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3583 SILC_STATUS_ERR_NO_ROUTER_PRIV);
3587 /* Get the remote server */
3588 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3591 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3596 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3598 SILC_GET32_MSB(port, tmp);
3600 /* Create the connection. It is done with timeout and is async. */
3601 silc_server_create_connection(server, host, port);
3603 /* Send reply to the sender */
3604 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3608 silc_server_command_free(cmd);
3611 SILC_SERVER_CMD_FUNC(restart)
3615 /* Server side command of CLOSE. Closes connection to a specified server. */
3617 SILC_SERVER_CMD_FUNC(close)
3619 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3620 SilcServer server = cmd->server;
3621 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3622 SilcServerEntry server_entry;
3623 SilcSocketConnection sock;
3625 unsigned int tmp_len;
3626 unsigned char *name;
3627 unsigned int port = SILC_PORT;
3629 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3631 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3634 /* Check whether client has the permissions. */
3635 if (client->mode == SILC_UMODE_NONE) {
3636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3637 SILC_STATUS_ERR_NO_SERVER_PRIV);
3641 /* Get the remote server */
3642 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3644 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3645 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3650 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3652 SILC_GET32_MSB(port, tmp);
3654 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3656 if (!server_entry) {
3657 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3658 SILC_STATUS_ERR_NO_SERVER_ID);
3662 /* Send reply to the sender */
3663 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3666 /* Close the connection to the server */
3667 sock = (SilcSocketConnection)server_entry->connection;
3668 silc_server_free_sock_user_data(server, sock);
3669 silc_server_close_connection(server, sock);
3672 silc_server_command_free(cmd);
3675 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3676 active connections. */
3678 SILC_SERVER_CMD_FUNC(shutdown)
3680 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3681 SilcServer server = cmd->server;
3682 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3684 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3686 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3689 /* Check whether client has the permission. */
3690 if (client->mode == SILC_UMODE_NONE) {
3691 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3692 SILC_STATUS_ERR_NO_SERVER_PRIV);
3696 /* Send reply to the sender */
3697 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3700 /* Then, gracefully, or not, bring the server down. */
3701 silc_server_stop(server);
3705 silc_server_command_free(cmd);
3708 /* Server side command of LEAVE. Removes client from a channel. */
3710 SILC_SERVER_CMD_FUNC(leave)
3712 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3713 SilcServer server = cmd->server;
3714 SilcSocketConnection sock = cmd->sock;
3715 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3717 SilcChannelEntry channel;
3719 unsigned int i, len;
3722 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3724 /* Get Channel ID */
3725 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3728 SILC_STATUS_ERR_NO_CHANNEL_ID);
3731 id = silc_id_payload_parse_id(tmp, len);
3733 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3734 SILC_STATUS_ERR_NO_CHANNEL_ID);
3738 /* Get channel entry */
3739 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3741 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3743 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3744 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3749 /* Check whether this client is on the channel */
3750 if (!silc_server_client_on_channel(id_entry, channel)) {
3751 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3752 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3756 /* Notify routers that they should remove this client from their list
3757 of clients on the channel. Send LEAVE notify type. */
3758 if (!server->standalone)
3759 silc_server_send_notify_leave(server, server->router->connection,
3760 server->server_type == SILC_ROUTER ?
3761 TRUE : FALSE, channel, id_entry->id,
3762 SILC_ID_CLIENT_LEN);
3764 /* Remove client from channel */
3765 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3770 /* If the channel does not exist anymore we won't send anything */
3774 /* Re-generate channel key */
3775 silc_server_create_channel_key(server, channel, 0);
3777 /* Encode channel key payload to be distributed on the channel */
3779 silc_channel_key_payload_encode(len, tmp,
3780 strlen(channel->channel_key->cipher->name),
3781 channel->channel_key->cipher->name,
3782 channel->key_len / 8, channel->key);
3784 /* If we are normal server then we will send it to our router. If we
3785 are router we will send it to all local servers that has clients on
3787 if (server->server_type == SILC_SERVER) {
3788 if (!server->standalone)
3789 silc_server_packet_send(server,
3790 cmd->server->router->connection,
3791 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3792 packet->len, FALSE);
3797 /* Send to locally connected clients on the channel */
3798 silc_server_packet_send_local_channel(server, channel,
3799 SILC_PACKET_CHANNEL_KEY, 0,
3800 packet->data, packet->len, FALSE);
3802 silc_buffer_free(packet);
3806 silc_server_command_free(cmd);
3809 /* Server side of command USERS. Resolves clients and their USERS currently
3810 joined on the requested channel. The list of Client ID's and their modes
3811 on the channel is sent back. */
3813 SILC_SERVER_CMD_FUNC(users)
3815 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3816 SilcServer server = cmd->server;
3817 SilcChannelEntry channel;
3820 unsigned char *channel_id;
3821 unsigned int channel_id_len;
3822 SilcBuffer client_id_list;
3823 SilcBuffer client_mode_list;
3824 unsigned char lc[4];
3825 unsigned int list_count = 0;
3826 unsigned short ident = silc_command_get_ident(cmd->payload);
3828 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3830 /* Get Channel ID */
3831 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3834 SILC_STATUS_ERR_NO_CHANNEL_ID);
3837 id = silc_id_payload_parse_id(channel_id, channel_id_len);
3839 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3840 SILC_STATUS_ERR_NO_CHANNEL_ID);
3844 /* If we are server and we don't know about this channel we will send
3845 the command to our router. If we know about the channel then we also
3846 have the list of users already. */
3847 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3849 if (server->server_type == SILC_SERVER && !server->standalone &&
3853 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3854 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3856 /* Send USERS command */
3857 silc_server_packet_send(server, server->router->connection,
3858 SILC_PACKET_COMMAND, cmd->packet->flags,
3859 tmpbuf->data, tmpbuf->len, TRUE);
3861 /* Reprocess this packet after received reply */
3862 silc_server_command_pending(server, SILC_COMMAND_USERS,
3863 silc_command_get_ident(cmd->payload),
3864 silc_server_command_destructor,
3865 silc_server_command_users,
3866 silc_server_command_dup(cmd));
3867 cmd->pending = TRUE;
3868 silc_command_set_ident(cmd->payload, ident);
3870 silc_buffer_free(tmpbuf);
3875 /* We are router and we will check the global list as well. */
3876 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3878 /* Channel really does not exist */
3879 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3880 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3885 /* Get the users list */
3886 silc_server_get_users_on_channel(server, channel, &client_id_list,
3887 &client_mode_list, &list_count);
3890 SILC_PUT32_MSB(list_count, lc);
3893 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3894 SILC_STATUS_OK, ident, 4,
3895 2, channel_id, channel_id_len,
3897 4, client_id_list->data,
3898 client_id_list->len,
3899 5, client_mode_list->data,
3900 client_mode_list->len);
3901 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3902 packet->data, packet->len, FALSE);
3904 silc_buffer_free(packet);
3905 silc_buffer_free(client_id_list);
3906 silc_buffer_free(client_mode_list);
3910 silc_server_command_free(cmd);