5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
37 unsigned int arg_type,
39 unsigned int arg_len);
40 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
45 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
49 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
50 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
54 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(connect, CONNECT,
56 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
60 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
63 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
65 SILC_SERVER_CMD(restart, RESTART,
66 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
67 SILC_SERVER_CMD(close, CLOSE,
68 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
69 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
71 SILC_SERVER_CMD(silcoper, SILCOPER,
72 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
73 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
74 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
79 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
81 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
83 SILC_LOG_DEBUG(("Start")); \
86 silc_server_command_send_status_reply(cmd, command, \
87 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
88 silc_server_command_free(cmd); \
92 silc_server_command_send_status_reply(cmd, command, \
93 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
94 silc_server_command_free(cmd); \
99 /* Returns TRUE if the connection is registered. Unregistered connections
100 usually cannot send commands hence the check. */
102 static int silc_server_is_registered(SilcServer server,
103 SilcSocketConnection sock,
104 SilcServerCommandContext cmd,
107 SilcIDListData idata = (SilcIDListData)sock->user_data;
108 if (idata->registered)
111 silc_server_command_send_status_reply(cmd, command,
112 SILC_STATUS_ERR_NOT_REGISTERED);
113 silc_server_command_free(cmd);
117 /* Internal context to hold data when executed command with timeout. */
119 SilcServerCommandContext ctx;
120 SilcServerCommand *cmd;
121 } *SilcServerCommandTimeout;
123 /* Timeout callback to process commands with timeout for client. Client's
124 commands are always executed with timeout. */
126 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
128 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
129 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
131 /* Update access time */
132 client->last_command = time(NULL);
134 if (!(timeout->cmd->flags & SILC_CF_REG))
135 timeout->cmd->cb(timeout->ctx);
136 else if (silc_server_is_registered(timeout->ctx->server,
140 timeout->cmd->cb(timeout->ctx);
145 /* Processes received command packet. */
147 void silc_server_command_process(SilcServer server,
148 SilcSocketConnection sock,
149 SilcPacketContext *packet)
151 SilcServerCommandContext ctx;
152 SilcServerCommand *cmd;
155 /* Allocate command context. This must be free'd by the
156 command routine receiving it. */
157 ctx = silc_server_command_alloc();
158 ctx->server = server;
159 ctx->sock = silc_socket_dup(sock);
160 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
162 /* Parse the command payload in the packet */
163 ctx->payload = silc_command_payload_parse(packet->buffer);
165 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
166 silc_buffer_free(packet->buffer);
167 silc_packet_context_free(packet);
168 silc_socket_free(ctx->sock);
172 ctx->args = silc_command_get_args(ctx->payload);
174 /* Get the command */
175 command = silc_command_get(ctx->payload);
176 for (cmd = silc_command_list; cmd->cb; cmd++)
177 if (cmd->cmd == command)
181 silc_server_command_send_status_reply(ctx, command,
182 SILC_STATUS_ERR_UNKNOWN_COMMAND);
183 silc_server_command_free(ctx);
187 /* Execute client's commands always with timeout. Normally they are
188 executed with zero (0) timeout but if client is sending command more
189 frequently than once in 2 seconds, then the timeout may be 0 to 2
191 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
192 SilcClientEntry client = (SilcClientEntry)sock->user_data;
193 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
199 if (client->last_command && (time(NULL) - client->last_command) < 2) {
200 client->fast_command++;
203 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
204 client->fast_command--);
208 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
209 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
210 silc_task_register(server->timeout_queue, sock->sock,
211 silc_server_command_process_timeout,
213 2 - (time(NULL) - client->last_command), 0,
215 SILC_TASK_PRI_NORMAL);
217 silc_task_register(server->timeout_queue, sock->sock,
218 silc_server_command_process_timeout,
222 SILC_TASK_PRI_NORMAL);
226 /* Execute for server */
228 if (!(cmd->flags & SILC_CF_REG))
230 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
234 /* Allocate Command Context */
236 SilcServerCommandContext silc_server_command_alloc()
238 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
243 /* Free's the command context allocated before executing the command */
245 void silc_server_command_free(SilcServerCommandContext ctx)
248 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
250 if (ctx->users < 1) {
252 silc_command_free_payload(ctx->payload);
254 silc_packet_context_free(ctx->packet);
256 silc_socket_free(ctx->sock); /* Decrease reference counter */
261 /* Duplicate Command Context by adding reference counter. The context won't
262 be free'd untill it hits zero. */
264 SilcServerCommandContext
265 silc_server_command_dup(SilcServerCommandContext ctx)
268 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
273 /* Add new pending command to be executed when reply to a command has been
274 received. The `reply_cmd' is the command that will call the `callback'
275 with `context' when reply has been received. If `ident' is non-zero
276 the `callback' will be executed when received reply with command
277 identifier `ident'. */
279 void silc_server_command_pending(SilcServer server,
280 SilcCommand reply_cmd,
281 unsigned short ident,
282 SilcServerPendingDestructor destructor,
283 SilcCommandCb callback,
286 SilcServerCommandPending *reply;
288 reply = silc_calloc(1, sizeof(*reply));
289 reply->reply_cmd = reply_cmd;
290 reply->ident = ident;
291 reply->context = context;
292 reply->callback = callback;
293 reply->destructor = destructor;
294 silc_dlist_add(server->pending_commands, reply);
297 /* Deletes pending command by reply command type. */
299 void silc_server_command_pending_del(SilcServer server,
300 SilcCommand reply_cmd,
301 unsigned short ident)
303 SilcServerCommandPending *r;
305 silc_dlist_start(server->pending_commands);
306 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
307 if (r->reply_cmd == reply_cmd && r->ident == ident) {
308 silc_dlist_del(server->pending_commands, r);
314 /* Checks for pending commands and marks callbacks to be called from
315 the command reply function. Returns TRUE if there were pending command. */
317 int silc_server_command_pending_check(SilcServer server,
318 SilcServerCommandReplyContext ctx,
320 unsigned short ident)
322 SilcServerCommandPending *r;
324 silc_dlist_start(server->pending_commands);
325 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
326 if (r->reply_cmd == command && r->ident == ident) {
327 ctx->context = r->context;
328 ctx->callback = r->callback;
329 ctx->destructor = r->destructor;
338 /* Destructor function for pending callbacks. This is called when using
339 pending commands to free the context given for the pending command. */
341 static void silc_server_command_destructor(void *context)
343 silc_server_command_free((SilcServerCommandContext)context);
346 /* Sends simple status message as command reply packet */
349 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
351 SilcCommandStatus status)
355 SILC_LOG_DEBUG(("Sending command status %d", status));
358 silc_command_reply_payload_encode_va(command, status,
359 silc_command_get_ident(cmd->payload),
361 silc_server_packet_send(cmd->server, cmd->sock,
362 SILC_PACKET_COMMAND_REPLY, 0,
363 buffer->data, buffer->len, FALSE);
364 silc_buffer_free(buffer);
367 /* Sends command status reply with one extra argument. The argument
368 type must be sent as argument. */
371 silc_server_command_send_status_data(SilcServerCommandContext cmd,
373 SilcCommandStatus status,
374 unsigned int arg_type,
376 unsigned int arg_len)
380 SILC_LOG_DEBUG(("Sending command status %d", status));
383 silc_command_reply_payload_encode_va(command, status,
384 silc_command_get_ident(cmd->payload),
385 1, arg_type, arg, arg_len);
386 silc_server_packet_send(cmd->server, cmd->sock,
387 SILC_PACKET_COMMAND_REPLY, 0,
388 buffer->data, buffer->len, FALSE);
389 silc_buffer_free(buffer);
392 /******************************************************************************
396 ******************************************************************************/
399 silc_server_command_whois_parse(SilcServerCommandContext cmd,
400 SilcClientID ***client_id,
401 unsigned int *client_id_count,
409 unsigned int argc = silc_argument_get_arg_num(cmd->args);
412 /* If client ID is in the command it must be used instead of nickname */
413 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
415 /* No ID, get the nickname@server string and parse it. */
416 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
418 if (strchr(tmp, '@')) {
419 len = strcspn(tmp, "@");
420 *nickname = silc_calloc(len + 1, sizeof(char));
421 memcpy(*nickname, tmp, len);
422 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
423 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
425 *nickname = strdup(tmp);
428 silc_server_command_send_status_reply(cmd, command,
429 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
433 /* Command includes ID, we must use that. Also check whether the command
434 has more than one ID set - take them all. */
436 *client_id = silc_calloc(1, sizeof(**client_id));
437 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
438 if ((*client_id)[0] == NULL) {
439 silc_free(*client_id);
442 *client_id_count = 1;
444 /* Take all ID's from the command packet */
446 for (k = 1, i = 1; i < argc; i++) {
447 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
449 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
450 (*client_id_count + 1));
451 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
452 if ((*client_id)[k] == NULL) {
453 /* Cleanup all and fail */
454 for (i = 0; i < *client_id_count; i++)
455 silc_free((*client_id)[i]);
456 silc_free(*client_id);
459 (*client_id_count)++;
465 /* Command includes ID, use that */
468 /* Get the max count of reply messages allowed */
469 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
479 silc_server_command_whois_check(SilcServerCommandContext cmd,
480 SilcClientEntry *clients,
481 unsigned int clients_count)
483 SilcServer server = cmd->server;
485 SilcClientEntry entry;
487 for (i = 0; i < clients_count; i++) {
490 if (entry->data.registered == FALSE)
493 if (!entry->nickname || !entry->username || !entry->userinfo) {
495 unsigned short old_ident;
500 old_ident = silc_command_get_ident(cmd->payload);
501 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
502 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
504 /* Send WHOIS command */
505 silc_server_packet_send(server, entry->router->connection,
506 SILC_PACKET_COMMAND, cmd->packet->flags,
507 tmpbuf->data, tmpbuf->len, TRUE);
509 /* Reprocess this packet after received reply */
510 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
511 silc_command_get_ident(cmd->payload),
512 silc_server_command_destructor,
513 silc_server_command_whois,
514 silc_server_command_dup(cmd));
517 silc_command_set_ident(cmd->payload, old_ident);
519 silc_buffer_free(tmpbuf);
528 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
529 SilcClientEntry *clients,
530 unsigned int clients_count)
532 SilcServer server = cmd->server;
534 int i, count = 0, len;
535 SilcBuffer packet, idp, channels;
536 SilcClientEntry entry;
537 SilcCommandStatus status;
538 unsigned short ident = silc_command_get_ident(cmd->payload);
539 char nh[128], uh[128];
540 unsigned char idle[4], mode[4];
541 SilcSocketConnection hsock;
543 status = SILC_STATUS_OK;
544 if (clients_count > 1)
545 status = SILC_STATUS_LIST_START;
547 for (i = 0; i < clients_count; i++) {
550 if (entry->data.registered == FALSE) {
551 if (clients_count == 1) {
552 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
553 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
554 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
555 2, idp->data, idp->len);
556 silc_buffer_free(idp);
561 if (count && i - 1 == count)
564 if (clients_count > 2)
565 status = SILC_STATUS_LIST_ITEM;
567 if (clients_count > 1 && i == clients_count - 1)
568 status = SILC_STATUS_LIST_END;
570 /* Sanity check, however these should never fail. However, as
571 this sanity check has been added here they have failed. */
572 if (!entry->nickname || !entry->username || !entry->userinfo)
575 /* Send WHOIS reply */
576 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
577 tmp = silc_argument_get_first_arg(cmd->args, NULL);
579 memset(uh, 0, sizeof(uh));
580 memset(nh, 0, sizeof(nh));
581 memset(idle, 0, sizeof(idle));
583 strncat(nh, entry->nickname, strlen(entry->nickname));
584 if (!strchr(entry->nickname, '@')) {
586 len = entry->router ? strlen(entry->router->server_name) :
587 strlen(server->server_name);
588 strncat(nh, entry->router ? entry->router->server_name :
589 server->server_name, len);
592 strncat(uh, entry->username, strlen(entry->username));
593 if (!strchr(entry->username, '@')) {
595 hsock = (SilcSocketConnection)entry->connection;
596 len = strlen(hsock->hostname);
597 strncat(uh, hsock->hostname, len);
600 channels = silc_server_get_client_channel_list(server, entry);
602 SILC_PUT32_MSB(entry->mode, mode);
604 if (entry->connection) {
605 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
609 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
611 2, idp->data, idp->len,
615 strlen(entry->userinfo),
621 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
623 2, idp->data, idp->len,
627 strlen(entry->userinfo),
631 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
632 0, packet->data, packet->len, FALSE);
634 silc_buffer_free(packet);
635 silc_buffer_free(idp);
637 silc_buffer_free(channels);
642 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
644 SilcServer server = cmd->server;
645 char *nick = NULL, *server_name = NULL;
646 int count = 0, clients_count = 0;
647 SilcClientEntry *clients = NULL, entry;
648 SilcClientID **client_id = NULL;
649 unsigned int client_id_count = 0;
652 /* Protocol dictates that we must always send the received WHOIS request
653 to our router if we are normal server, so let's do it now unless we
654 are standalone. We will not send any replies to the client until we
655 have received reply from the router. */
656 if (server->server_type == SILC_SERVER && !cmd->pending &&
657 !server->standalone) {
659 unsigned short old_ident;
661 old_ident = silc_command_get_ident(cmd->payload);
662 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
663 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
665 /* Send WHOIS command to our router */
666 silc_server_packet_send(server, (SilcSocketConnection)
667 server->router->connection,
668 SILC_PACKET_COMMAND, cmd->packet->flags,
669 tmpbuf->data, tmpbuf->len, TRUE);
671 /* Reprocess this packet after received reply from router */
672 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
673 silc_command_get_ident(cmd->payload),
674 silc_server_command_destructor,
675 silc_server_command_whois,
676 silc_server_command_dup(cmd));
679 silc_command_set_ident(cmd->payload, old_ident);
681 silc_buffer_free(tmpbuf);
686 /* We are ready to process the command request. Let's search for the
687 requested client and send reply to the requesting client. */
689 /* Parse the whois request */
690 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
691 &nick, &server_name, &count,
695 /* Get all clients matching that ID or nickname from local list */
696 if (client_id_count) {
697 /* Check all Client ID's received in the command packet */
698 for (i = 0; i < client_id_count; i++) {
699 entry = silc_idlist_find_client_by_id(server->local_list,
702 clients = silc_realloc(clients, sizeof(*clients) *
703 (clients_count + 1));
704 clients[clients_count++] = entry;
708 clients = silc_idlist_get_clients_by_hash(server->local_list,
709 nick, server->md5hash,
712 clients = silc_idlist_get_clients_by_nickname(server->local_list,
717 /* Check global list as well */
719 if (client_id_count) {
720 /* Check all Client ID's received in the command packet */
721 for (i = 0; i < client_id_count; i++) {
722 entry = silc_idlist_find_client_by_id(server->global_list,
725 clients = silc_realloc(clients, sizeof(*clients) *
726 (clients_count + 1));
727 clients[clients_count++] = entry;
731 clients = silc_idlist_get_clients_by_hash(server->global_list,
732 nick, server->md5hash,
735 clients = silc_idlist_get_clients_by_nickname(server->global_list,
742 /* Such client(s) really does not exist in the SILC network. */
743 if (!client_id_count) {
744 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
745 SILC_STATUS_ERR_NO_SUCH_NICK,
746 3, nick, strlen(nick));
748 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
749 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
750 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
751 2, idp->data, idp->len);
752 silc_buffer_free(idp);
757 /* Router always finds the client entry if it exists in the SILC network.
758 However, it might be incomplete entry and does not include all the
759 mandatory fields that WHOIS command reply requires. Check for these and
760 make query from the server who owns the client if some fields are
762 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
767 /* Send the command reply to the client */
768 silc_server_command_whois_send_reply(cmd, clients, clients_count);
771 if (client_id_count) {
772 for (i = 0; i < client_id_count; i++)
773 silc_free(client_id[i]);
774 silc_free(client_id);
781 silc_free(server_name);
787 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
789 SilcServer server = cmd->server;
790 char *nick = NULL, *server_name = NULL;
791 int count = 0, clients_count = 0;
792 SilcClientEntry *clients = NULL, entry;
793 SilcClientID **client_id = NULL;
794 unsigned int client_id_count = 0;
797 /* Parse the whois request */
798 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
799 &nick, &server_name, &count,
803 /* Process the command request. Let's search for the requested client and
804 send reply to the requesting server. */
806 if (client_id_count) {
807 /* Check all Client ID's received in the command packet */
808 for (i = 0; i < client_id_count; i++) {
809 entry = silc_idlist_find_client_by_id(server->local_list,
812 clients = silc_realloc(clients, sizeof(*clients) *
813 (clients_count + 1));
814 clients[clients_count++] = entry;
818 clients = silc_idlist_get_clients_by_hash(server->local_list,
819 nick, server->md5hash,
822 clients = silc_idlist_get_clients_by_nickname(server->local_list,
827 /* If we are router we will check our global list as well. */
828 if (!clients && server->server_type == SILC_ROUTER) {
829 if (client_id_count) {
830 /* Check all Client ID's received in the command packet */
831 for (i = 0; i < client_id_count; i++) {
832 entry = silc_idlist_find_client_by_id(server->global_list,
835 clients = silc_realloc(clients, sizeof(*clients) *
836 (clients_count + 1));
837 clients[clients_count++] = entry;
841 clients = silc_idlist_get_clients_by_hash(server->global_list,
842 nick, server->md5hash,
845 clients = silc_idlist_get_clients_by_nickname(server->global_list,
852 /* Such a client really does not exist in the SILC network. */
853 if (!client_id_count) {
854 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
855 SILC_STATUS_ERR_NO_SUCH_NICK,
856 3, nick, strlen(nick));
858 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
859 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
860 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
861 2, idp->data, idp->len);
862 silc_buffer_free(idp);
867 /* Router always finds the client entry if it exists in the SILC network.
868 However, it might be incomplete entry and does not include all the
869 mandatory fields that WHOIS command reply requires. Check for these and
870 make query from the server who owns the client if some fields are
872 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
877 /* Send the command reply to the client */
878 silc_server_command_whois_send_reply(cmd, clients, clients_count);
881 if (client_id_count) {
882 for (i = 0; i < client_id_count; i++)
883 silc_free(client_id[i]);
884 silc_free(client_id);
891 silc_free(server_name);
896 /* Server side of command WHOIS. Processes user's query and sends found
897 results as command replies back to the client. */
899 SILC_SERVER_CMD_FUNC(whois)
901 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
904 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
906 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
907 ret = silc_server_command_whois_from_client(cmd);
908 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
909 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
910 ret = silc_server_command_whois_from_server(cmd);
913 silc_server_command_free(cmd);
916 /******************************************************************************
920 ******************************************************************************/
923 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
931 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
934 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
938 /* Get the nickname@server string and parse it. */
939 if (strchr(tmp, '@')) {
940 len = strcspn(tmp, "@");
941 *nickname = silc_calloc(len + 1, sizeof(char));
942 memcpy(*nickname, tmp, len);
943 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
944 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
946 *nickname = strdup(tmp);
948 /* Get the max count of reply messages allowed */
949 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
959 silc_server_command_whowas_check(SilcServerCommandContext cmd,
960 SilcClientEntry *clients,
961 unsigned int clients_count)
963 SilcServer server = cmd->server;
965 SilcClientEntry entry;
967 for (i = 0; i < clients_count; i++) {
970 if (!entry->nickname || !entry->username) {
972 unsigned short old_ident;
977 old_ident = silc_command_get_ident(cmd->payload);
978 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
979 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
981 /* Send WHOWAS command */
982 silc_server_packet_send(server, entry->router->connection,
983 SILC_PACKET_COMMAND, cmd->packet->flags,
984 tmpbuf->data, tmpbuf->len, TRUE);
986 /* Reprocess this packet after received reply */
987 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
988 silc_command_get_ident(cmd->payload),
989 silc_server_command_destructor,
990 silc_server_command_whowas,
991 silc_server_command_dup(cmd));
994 silc_command_set_ident(cmd->payload, old_ident);
996 silc_buffer_free(tmpbuf);
1005 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1006 SilcClientEntry *clients,
1007 unsigned int clients_count)
1009 SilcServer server = cmd->server;
1011 int i, count = 0, len;
1012 SilcBuffer packet, idp;
1013 SilcClientEntry entry = NULL;
1014 SilcCommandStatus status;
1015 unsigned short ident = silc_command_get_ident(cmd->payload);
1017 char nh[256], uh[256];
1019 status = SILC_STATUS_OK;
1020 if (clients_count > 1)
1021 status = SILC_STATUS_LIST_START;
1023 for (i = 0; i < clients_count; i++) {
1026 /* We will take only clients that are not valid anymore. They are the
1027 ones that are not registered anymore but still have a ID. They
1028 have disconnected us, and thus valid for WHOWAS. */
1029 if (entry->data.registered == TRUE)
1031 if (entry->id == NULL)
1034 if (count && i - 1 == count)
1039 if (clients_count > 2)
1040 status = SILC_STATUS_LIST_ITEM;
1042 if (clients_count > 1 && i == clients_count - 1)
1043 status = SILC_STATUS_LIST_END;
1045 /* Sanity check, however these should never fail. However, as
1046 this sanity check has been added here they have failed. */
1047 if (!entry->nickname || !entry->username)
1050 /* Send WHOWAS reply */
1051 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1052 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1054 memset(uh, 0, sizeof(uh));
1055 memset(nh, 0, sizeof(nh));
1057 strncat(nh, entry->nickname, strlen(entry->nickname));
1058 if (!strchr(entry->nickname, '@')) {
1059 strncat(nh, "@", 1);
1060 len = entry->router ? strlen(entry->router->server_name) :
1061 strlen(server->server_name);
1062 strncat(nh, entry->router ? entry->router->server_name :
1063 server->server_name, len);
1066 strncat(uh, entry->username, strlen(entry->username));
1067 if (!strchr(entry->username, '@')) {
1068 strncat(uh, "@", 1);
1069 strcat(uh, "*private*");
1072 if (entry->userinfo)
1074 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1076 2, idp->data, idp->len,
1080 strlen(entry->userinfo));
1083 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1085 2, idp->data, idp->len,
1089 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1090 0, packet->data, packet->len, FALSE);
1092 silc_buffer_free(packet);
1093 silc_buffer_free(idp);
1096 if (found == FALSE && entry)
1097 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1098 SILC_STATUS_ERR_NO_SUCH_NICK,
1100 strlen(entry->nickname));
1104 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1106 SilcServer server = cmd->server;
1107 char *nick = NULL, *server_name = NULL;
1108 int count = 0, clients_count = 0;
1109 SilcClientEntry *clients = NULL;
1112 /* Protocol dictates that we must always send the received WHOWAS request
1113 to our router if we are normal server, so let's do it now unless we
1114 are standalone. We will not send any replies to the client until we
1115 have received reply from the router. */
1116 if (server->server_type == SILC_SERVER &&
1117 !cmd->pending && !server->standalone) {
1119 unsigned short old_ident;
1121 old_ident = silc_command_get_ident(cmd->payload);
1122 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1123 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1125 /* Send WHOWAS command to our router */
1126 silc_server_packet_send(server, (SilcSocketConnection)
1127 server->router->connection,
1128 SILC_PACKET_COMMAND, cmd->packet->flags,
1129 tmpbuf->data, tmpbuf->len, TRUE);
1131 /* Reprocess this packet after received reply from router */
1132 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1133 silc_command_get_ident(cmd->payload),
1134 silc_server_command_destructor,
1135 silc_server_command_whowas,
1136 silc_server_command_dup(cmd));
1137 cmd->pending = TRUE;
1139 silc_command_set_ident(cmd->payload, old_ident);
1141 silc_buffer_free(tmpbuf);
1146 /* We are ready to process the command request. Let's search for the
1147 requested client and send reply to the requesting client. */
1149 /* Parse the whowas request */
1150 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1153 /* Get all clients matching that nickname from local list */
1154 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1158 clients = silc_idlist_get_clients_by_hash(server->local_list,
1159 nick, server->md5hash,
1162 /* Check global list as well */
1164 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1168 clients = silc_idlist_get_clients_by_hash(server->global_list,
1169 nick, server->md5hash,
1173 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1178 /* Send the command reply to the client */
1179 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1187 silc_free(server_name);
1193 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1195 SilcServer server = cmd->server;
1196 char *nick = NULL, *server_name = NULL;
1197 int count = 0, clients_count = 0;
1198 SilcClientEntry *clients = NULL;
1201 /* Parse the whowas request */
1202 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1205 /* Process the command request. Let's search for the requested client and
1206 send reply to the requesting server. */
1208 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1212 clients = silc_idlist_get_clients_by_hash(server->local_list,
1213 nick, server->md5hash,
1216 /* If we are router we will check our global list as well. */
1217 if (!clients && server->server_type == SILC_ROUTER) {
1218 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1222 clients = silc_idlist_get_clients_by_hash(server->global_list,
1223 nick, server->md5hash,
1228 /* Such a client really does not exist in the SILC network. */
1229 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1230 SILC_STATUS_ERR_NO_SUCH_NICK,
1231 3, nick, strlen(nick));
1235 /* Send the command reply to the client */
1236 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1244 silc_free(server_name);
1249 /* Server side of command WHOWAS. */
1251 SILC_SERVER_CMD_FUNC(whowas)
1253 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1256 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1258 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1259 ret = silc_server_command_whowas_from_client(cmd);
1260 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1261 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1262 ret = silc_server_command_whowas_from_server(cmd);
1265 silc_server_command_free(cmd);
1268 /******************************************************************************
1272 ******************************************************************************/
1274 /* Checks that all mandatory fields are present. If not then send WHOIS
1275 request to the server who owns the client. We use WHOIS because we want
1276 to get as much information as possible at once. */
1279 silc_server_command_identify_check(SilcServerCommandContext cmd,
1280 SilcClientEntry *clients,
1281 unsigned int clients_count)
1283 SilcServer server = cmd->server;
1285 SilcClientEntry entry;
1287 for (i = 0; i < clients_count; i++) {
1290 if (entry->data.registered == FALSE)
1293 if (!entry->nickname) {
1295 unsigned short old_ident;
1300 old_ident = silc_command_get_ident(cmd->payload);
1301 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1302 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1303 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1305 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1306 now anyway so make it a good one. */
1307 silc_server_packet_send(server, entry->router->connection,
1308 SILC_PACKET_COMMAND, cmd->packet->flags,
1309 tmpbuf->data, tmpbuf->len, TRUE);
1311 /* Reprocess this packet after received reply */
1312 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1313 silc_command_get_ident(cmd->payload),
1314 silc_server_command_destructor,
1315 silc_server_command_identify,
1316 silc_server_command_dup(cmd));
1318 cmd->pending = TRUE;
1320 /* Put old data back to the Command Payload we just changed */
1321 silc_command_set_ident(cmd->payload, old_ident);
1322 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1324 silc_buffer_free(tmpbuf);
1333 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1334 SilcClientEntry *clients,
1335 unsigned int clients_count)
1337 SilcServer server = cmd->server;
1339 int i, count = 0, len;
1340 SilcBuffer packet, idp;
1341 SilcClientEntry entry;
1342 SilcCommandStatus status;
1343 unsigned short ident = silc_command_get_ident(cmd->payload);
1345 status = SILC_STATUS_OK;
1346 if (clients_count > 1)
1347 status = SILC_STATUS_LIST_START;
1349 for (i = 0; i < clients_count; i++) {
1352 if (entry->data.registered == FALSE) {
1353 if (clients_count == 1) {
1354 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1355 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1356 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1357 2, idp->data, idp->len);
1358 silc_buffer_free(idp);
1363 if (count && i - 1 == count)
1366 if (clients_count > 2)
1367 status = SILC_STATUS_LIST_ITEM;
1369 if (clients_count > 1 && i == clients_count - 1)
1370 status = SILC_STATUS_LIST_END;
1372 /* Send IDENTIFY reply */
1373 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1374 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1378 char nh[256], uh[256];
1379 SilcSocketConnection hsock;
1381 memset(uh, 0, sizeof(uh));
1382 memset(nh, 0, sizeof(nh));
1384 strncat(nh, entry->nickname, strlen(entry->nickname));
1385 if (!strchr(entry->nickname, '@')) {
1386 strncat(nh, "@", 1);
1387 len = entry->router ? strlen(entry->router->server_name) :
1388 strlen(server->server_name);
1389 strncat(nh, entry->router ? entry->router->server_name :
1390 server->server_name, len);
1393 if (!entry->username) {
1394 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1396 2, idp->data, idp->len,
1399 strncat(uh, entry->username, strlen(entry->username));
1400 if (!strchr(entry->username, '@')) {
1401 strncat(uh, "@", 1);
1402 hsock = (SilcSocketConnection)entry->connection;
1403 len = strlen(hsock->hostname);
1404 strncat(uh, hsock->hostname, len);
1407 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1409 2, idp->data, idp->len,
1414 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1415 0, packet->data, packet->len, FALSE);
1417 silc_buffer_free(packet);
1418 silc_buffer_free(idp);
1424 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1426 SilcServer server = cmd->server;
1427 char *nick = NULL, *server_name = NULL;
1428 int count = 0, clients_count = 0;
1429 SilcClientEntry *clients = NULL, entry;
1430 SilcClientID **client_id = NULL;
1431 unsigned int client_id_count = 0;
1434 /* Protocol dictates that we must always send the received IDENTIFY request
1435 to our router if we are normal server, so let's do it now unless we
1436 are standalone. We will not send any replies to the client until we
1437 have received reply from the router. */
1438 if (server->server_type == SILC_SERVER &&
1439 !cmd->pending && !server->standalone) {
1441 unsigned short old_ident;
1443 old_ident = silc_command_get_ident(cmd->payload);
1444 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1445 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1447 /* Send IDENTIFY command to our router */
1448 silc_server_packet_send(server, (SilcSocketConnection)
1449 server->router->connection,
1450 SILC_PACKET_COMMAND, cmd->packet->flags,
1451 tmpbuf->data, tmpbuf->len, TRUE);
1453 /* Reprocess this packet after received reply from router */
1454 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1455 silc_command_get_ident(cmd->payload),
1456 silc_server_command_destructor,
1457 silc_server_command_identify,
1458 silc_server_command_dup(cmd));
1459 cmd->pending = TRUE;
1461 silc_command_set_ident(cmd->payload, old_ident);
1463 silc_buffer_free(tmpbuf);
1468 /* We are ready to process the command request. Let's search for the
1469 requested client and send reply to the requesting client. */
1471 /* Parse the IDENTIFY request */
1472 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1473 &nick, &server_name, &count,
1474 SILC_COMMAND_IDENTIFY))
1477 /* Get all clients matching that ID or nickname from local list */
1478 if (client_id_count) {
1479 /* Check all Client ID's received in the command packet */
1480 for (i = 0; i < client_id_count; i++) {
1481 entry = silc_idlist_find_client_by_id(server->local_list,
1482 client_id[i], NULL);
1484 clients = silc_realloc(clients, sizeof(*clients) *
1485 (clients_count + 1));
1486 clients[clients_count++] = entry;
1490 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1494 clients = silc_idlist_get_clients_by_hash(server->local_list,
1495 nick, server->md5hash,
1499 /* Check global list as well */
1501 if (client_id_count) {
1502 /* Check all Client ID's received in the command packet */
1503 for (i = 0; i < client_id_count; i++) {
1504 entry = silc_idlist_find_client_by_id(server->global_list,
1505 client_id[i], NULL);
1507 clients = silc_realloc(clients, sizeof(*clients) *
1508 (clients_count + 1));
1509 clients[clients_count++] = entry;
1513 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1517 clients = silc_idlist_get_clients_by_hash(server->global_list,
1518 nick, server->md5hash,
1524 /* Such a client really does not exist in the SILC network. */
1525 if (!client_id_count) {
1526 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1527 SILC_STATUS_ERR_NO_SUCH_NICK,
1528 3, nick, strlen(nick));
1530 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1531 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1532 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1533 2, idp->data, idp->len);
1534 silc_buffer_free(idp);
1539 /* Check that all mandatory fields are present and request those data
1540 from the server who owns the client if necessary. */
1541 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1546 /* Send the command reply to the client */
1547 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1550 if (client_id_count) {
1551 for (i = 0; i < client_id_count; i++)
1552 silc_free(client_id[i]);
1553 silc_free(client_id);
1560 silc_free(server_name);
1566 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1568 SilcServer server = cmd->server;
1569 char *nick = NULL, *server_name = NULL;
1570 int count = 0, clients_count = 0;
1571 SilcClientEntry *clients = NULL, entry;
1572 SilcClientID **client_id = NULL;
1573 unsigned int client_id_count = 0;
1576 /* Parse the IDENTIFY request */
1577 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1578 &nick, &server_name, &count,
1579 SILC_COMMAND_IDENTIFY))
1582 /* Process the command request. Let's search for the requested client and
1583 send reply to the requesting server. */
1585 if (client_id_count) {
1586 /* Check all Client ID's received in the command packet */
1587 for (i = 0; i < client_id_count; i++) {
1588 entry = silc_idlist_find_client_by_id(server->local_list,
1589 client_id[i], NULL);
1591 clients = silc_realloc(clients, sizeof(*clients) *
1592 (clients_count + 1));
1593 clients[clients_count++] = entry;
1597 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1601 clients = silc_idlist_get_clients_by_hash(server->local_list,
1602 nick, server->md5hash,
1606 /* If we are router we will check our global list as well. */
1607 if (!clients && server->server_type == SILC_ROUTER) {
1608 if (client_id_count) {
1609 /* Check all Client ID's received in the command packet */
1610 for (i = 0; i < client_id_count; i++) {
1611 entry = silc_idlist_find_client_by_id(server->global_list,
1612 client_id[i], NULL);
1614 clients = silc_realloc(clients, sizeof(*clients) *
1615 (clients_count + 1));
1616 clients[clients_count++] = entry;
1620 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1624 clients = silc_idlist_get_clients_by_hash(server->global_list,
1625 nick, server->md5hash,
1631 /* Such a client really does not exist in the SILC network. */
1632 if (!client_id_count) {
1633 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1634 SILC_STATUS_ERR_NO_SUCH_NICK,
1635 3, nick, strlen(nick));
1637 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1638 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1639 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1640 2, idp->data, idp->len);
1641 silc_buffer_free(idp);
1646 /* Check that all mandatory fields are present and request those data
1647 from the server who owns the client if necessary. */
1648 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1653 /* Send the command reply */
1654 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1657 if (client_id_count) {
1658 for (i = 0; i < client_id_count; i++)
1659 silc_free(client_id[i]);
1660 silc_free(client_id);
1667 silc_free(server_name);
1672 SILC_SERVER_CMD_FUNC(identify)
1674 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1677 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1679 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1680 ret = silc_server_command_identify_from_client(cmd);
1681 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1682 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1683 ret = silc_server_command_identify_from_server(cmd);
1686 silc_server_command_free(cmd);
1689 /* Checks string for bad characters and returns TRUE if they are found. */
1691 static int silc_server_command_bad_chars(char *nick)
1693 if (strchr(nick, '\\')) return TRUE;
1694 if (strchr(nick, '\"')) return TRUE;
1695 if (strchr(nick, '´')) return TRUE;
1696 if (strchr(nick, '`')) return TRUE;
1697 if (strchr(nick, '\'')) return TRUE;
1698 if (strchr(nick, '*')) return TRUE;
1699 if (strchr(nick, '/')) return TRUE;
1700 if (strchr(nick, '@')) return TRUE;
1705 /* Server side of command NICK. Sets nickname for user. Setting
1706 nickname causes generation of a new client ID for the client. The
1707 new client ID is sent to the client after changing the nickname. */
1709 SILC_SERVER_CMD_FUNC(nick)
1711 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1712 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1713 SilcServer server = cmd->server;
1714 SilcBuffer packet, nidp, oidp;
1715 SilcClientID *new_id;
1717 unsigned short ident = silc_command_get_ident(cmd->payload);
1719 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1722 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1724 /* Check nickname */
1725 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1726 if (silc_server_command_bad_chars(nick) == TRUE) {
1727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1728 SILC_STATUS_ERR_BAD_NICKNAME);
1732 if (strlen(nick) > 128)
1735 /* Create new Client ID */
1736 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1737 cmd->server->md5hash, nick,
1740 /* Send notify about nickname change to our router. We send the new
1741 ID and ask to replace it with the old one. If we are router the
1742 packet is broadcasted. Send NICK_CHANGE notify. */
1743 if (!server->standalone)
1744 silc_server_send_notify_nick_change(server, server->router->connection,
1745 server->server_type == SILC_SERVER ?
1746 FALSE : TRUE, client->id,
1747 new_id, SILC_ID_CLIENT_LEN);
1749 /* Remove old cache entry */
1750 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1753 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1757 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1758 silc_free(client->id);
1761 /* Save the nickname as this client is our local client */
1762 if (client->nickname)
1763 silc_free(client->nickname);
1765 client->nickname = strdup(nick);
1766 client->id = new_id;
1768 /* Update client cache */
1769 silc_idcache_add(server->local_list->clients, client->nickname,
1770 strlen(client->nickname), SILC_ID_CLIENT, client->id,
1771 (void *)client, TRUE, FALSE);
1773 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1775 /* Send NICK_CHANGE notify to the client's channels */
1776 silc_server_send_notify_on_channels(server, NULL, client,
1777 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1778 oidp->data, oidp->len,
1779 nidp->data, nidp->len);
1781 /* Send the new Client ID as reply command back to client */
1782 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1783 SILC_STATUS_OK, ident, 1,
1784 2, nidp->data, nidp->len);
1785 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1786 0, packet->data, packet->len, FALSE);
1788 silc_buffer_free(packet);
1789 silc_buffer_free(nidp);
1790 silc_buffer_free(oidp);
1793 silc_server_command_free(cmd);
1796 SILC_SERVER_CMD_FUNC(list)
1800 /* Server side of TOPIC command. Sets topic for channel and/or returns
1801 current topic to client. */
1803 SILC_SERVER_CMD_FUNC(topic)
1805 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1806 SilcServer server = cmd->server;
1807 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1808 SilcChannelID *channel_id;
1809 SilcChannelEntry channel;
1810 SilcChannelClientEntry chl;
1811 SilcBuffer packet, idp;
1813 unsigned int argc, tmp_len;
1814 unsigned short ident = silc_command_get_ident(cmd->payload);
1816 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1818 argc = silc_argument_get_arg_num(cmd->args);
1820 /* Get Channel ID */
1821 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1824 SILC_STATUS_ERR_NO_CHANNEL_ID);
1827 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1829 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1830 SILC_STATUS_ERR_NO_CHANNEL_ID);
1834 /* Check whether the channel exists */
1835 channel = silc_idlist_find_channel_by_id(server->local_list,
1838 channel = silc_idlist_find_channel_by_id(server->global_list,
1841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1842 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1849 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1851 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1852 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1856 if (strlen(tmp) > 256) {
1857 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1858 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1862 /* See whether has rights to change topic */
1863 silc_list_start(channel->user_list);
1864 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1865 if (chl->client == client)
1868 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1869 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1870 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1871 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1876 /* Set the topic for channel */
1878 silc_free(channel->topic);
1879 channel->topic = strdup(tmp);
1881 /* Send TOPIC_SET notify type to the network */
1882 if (!server->standalone)
1883 silc_server_send_notify_topic_set(server, server->router->connection,
1884 server->server_type == SILC_ROUTER ?
1885 TRUE : FALSE, channel, client->id,
1886 SILC_ID_CLIENT_LEN, channel->topic);
1888 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1890 /* Send notify about topic change to all clients on the channel */
1891 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1892 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1893 idp->data, idp->len,
1894 channel->topic, strlen(channel->topic));
1895 silc_buffer_free(idp);
1898 /* Send the topic to client as reply packet */
1899 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1901 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1902 SILC_STATUS_OK, ident, 2,
1903 2, idp->data, idp->len,
1905 strlen(channel->topic));
1907 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1908 SILC_STATUS_OK, ident, 1,
1909 2, idp->data, idp->len);
1910 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1911 0, packet->data, packet->len, FALSE);
1913 silc_buffer_free(packet);
1914 silc_buffer_free(idp);
1915 silc_free(channel_id);
1918 silc_server_command_free(cmd);
1921 /* Server side of INVITE command. Invites some client to join some channel. */
1923 SILC_SERVER_CMD_FUNC(invite)
1925 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1926 SilcServer server = cmd->server;
1927 SilcSocketConnection sock = cmd->sock, dest_sock;
1928 SilcClientEntry sender, dest;
1929 SilcClientID *dest_id;
1930 SilcChannelEntry channel;
1931 SilcChannelID *channel_id;
1936 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1938 /* Get destination ID */
1939 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1942 SILC_STATUS_ERR_NO_CLIENT_ID);
1945 dest_id = silc_id_payload_parse_id(tmp, len);
1947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1948 SILC_STATUS_ERR_NO_CLIENT_ID);
1952 /* Get Channel ID */
1953 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1956 SILC_STATUS_ERR_NO_CHANNEL_ID);
1959 channel_id = silc_id_payload_parse_id(tmp, len);
1961 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1962 SILC_STATUS_ERR_NO_CHANNEL_ID);
1966 /* Check whether the channel exists */
1967 channel = silc_idlist_find_channel_by_id(server->local_list,
1970 channel = silc_idlist_find_channel_by_id(server->global_list,
1973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1974 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1979 /* Check whether the sender of this command is on the channel. */
1980 sender = (SilcClientEntry)sock->user_data;
1981 if (!silc_server_client_on_channel(sender, channel)) {
1982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1983 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1987 /* Check whether the channel is invite-only channel. If yes then the
1988 sender of this command must be at least channel operator. */
1989 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1990 SilcChannelClientEntry chl;
1992 silc_list_start(channel->user_list);
1993 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1994 if (chl->client == sender) {
1995 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1996 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1997 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2004 /* Find the connection data for the destination. If it is local we will
2005 send it directly otherwise we will send it to router for routing. */
2006 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
2008 dest_sock = (SilcSocketConnection)dest->connection;
2010 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
2012 /* Check whether the requested client is already on the channel. */
2013 /* XXX if we are normal server we don't know about global clients on
2014 the channel thus we must request it (USERS command), check from
2015 local cache as well. */
2016 if (silc_server_client_on_channel(dest, channel)) {
2017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2018 SILC_STATUS_ERR_USER_ON_CHANNEL);
2022 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2024 /* Send notify to the client that is invited to the channel */
2025 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2027 SILC_NOTIFY_TYPE_INVITE, 2,
2028 sidp->data, sidp->len, tmp, len);
2030 /* Send command reply */
2031 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2034 silc_buffer_free(sidp);
2037 silc_server_command_free(cmd);
2042 SilcSocketConnection sock;
2046 /* Quits connection to client. This gets called if client won't
2047 close the connection even when it has issued QUIT command. */
2049 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2051 QuitInternal q = (QuitInternal)context;
2053 /* Free all client specific data, such as client entry and entires
2054 on channels this client may be on. */
2055 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2057 q->sock->user_data = NULL;
2059 /* Close the connection on our side */
2060 silc_server_close_connection(q->server, q->sock);
2062 silc_free(q->signoff);
2066 /* Quits SILC session. This is the normal way to disconnect client. */
2068 SILC_SERVER_CMD_FUNC(quit)
2070 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2071 SilcServer server = cmd->server;
2072 SilcSocketConnection sock = cmd->sock;
2074 unsigned char *tmp = NULL;
2075 unsigned int len = 0;
2077 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2079 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2082 /* Get destination ID */
2083 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2087 q = silc_calloc(1, sizeof(*q));
2090 q->signoff = tmp ? strdup(tmp) : NULL;
2092 /* We quit the connection with little timeout */
2093 silc_task_register(server->timeout_queue, sock->sock,
2094 silc_server_command_quit_cb, (void *)q,
2095 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2098 silc_server_command_free(cmd);
2101 /* Server side of command KILL. This command is used by router operator
2102 to remove an client from the SILC Network temporarily. */
2104 SILC_SERVER_CMD_FUNC(kill)
2106 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2107 SilcServer server = cmd->server;
2108 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2109 SilcClientEntry remote_client;
2110 SilcClientID *client_id;
2111 unsigned char *tmp, *comment;
2112 unsigned int tmp_len, tmp_len2;
2114 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2116 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2119 /* KILL command works only on router */
2120 if (server->server_type != SILC_ROUTER) {
2121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2122 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2126 /* Check whether client has the permissions. */
2127 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2128 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2129 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2133 /* Get the client ID */
2134 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2137 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2140 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2142 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2143 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2147 /* Get the client entry */
2148 remote_client = silc_idlist_find_client_by_id(server->local_list,
2150 if (!remote_client) {
2151 remote_client = silc_idlist_find_client_by_id(server->global_list,
2153 if (!remote_client) {
2154 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2155 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2161 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2165 /* Send reply to the sender */
2166 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2169 /* Send the KILL notify packets. First send it to the channel, then
2170 to our primary router and then directly to the client who is being
2171 killed right now. */
2173 /* Send KILLED notify to the channels. It is not sent to the client
2174 as it will be sent differently destined directly to the client and not
2176 silc_server_send_notify_on_channels(server, remote_client,
2177 remote_client, SILC_NOTIFY_TYPE_KILLED,
2180 comment, comment ? tmp_len2 : 0);
2182 /* Send KILLED notify to primary route */
2183 if (!server->standalone)
2184 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2185 remote_client->id, SILC_ID_CLIENT_LEN,
2188 /* Send KILLED notify to the client directly */
2189 silc_server_send_notify_killed(server, remote_client->connection ?
2190 remote_client->connection :
2191 remote_client->router->connection, FALSE,
2192 remote_client->id, SILC_ID_CLIENT_LEN,
2195 /* Remove the client from all channels. This generates new keys to the
2196 channels as well. */
2197 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2200 /* Remove the client entry, If it is locally connected then we will also
2201 disconnect the client here */
2202 if (remote_client->data.registered && remote_client->connection) {
2203 /* Remove locally conneted client */
2204 SilcSocketConnection sock = remote_client->connection;
2205 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2206 silc_server_close_connection(server, sock);
2208 /* Remove remote client */
2209 if (!silc_idlist_del_client(server->global_list, remote_client))
2210 silc_idlist_del_client(server->local_list, remote_client);
2214 silc_server_command_free(cmd);
2217 /* Server side of command INFO. This sends information about us to
2218 the client. If client requested specific server we will send the
2219 command to that server. */
2221 SILC_SERVER_CMD_FUNC(info)
2223 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2224 SilcServer server = cmd->server;
2225 SilcBuffer packet, idp;
2226 char *dest_server, *server_info = NULL, *server_name;
2227 unsigned short ident = silc_command_get_ident(cmd->payload);
2228 SilcServerEntry entry = NULL;
2230 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
2232 /* Get server name */
2233 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2235 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2236 SILC_STATUS_ERR_NO_SUCH_SERVER);
2240 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2241 /* Send our reply */
2242 char info_string[256];
2244 memset(info_string, 0, sizeof(info_string));
2245 snprintf(info_string, sizeof(info_string),
2246 "location: %s server: %s admin: %s <%s>",
2247 server->config->admin_info->location,
2248 server->config->admin_info->server_type,
2249 server->config->admin_info->admin_name,
2250 server->config->admin_info->admin_email);
2252 server_info = info_string;
2253 entry = server->id_entry;
2255 /* Check whether we have this server cached */
2256 entry = silc_idlist_find_server_by_name(server->global_list,
2259 entry = silc_idlist_find_server_by_name(server->local_list,
2263 if (server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2264 /* Send to the server */
2266 unsigned short old_ident;
2268 old_ident = silc_command_get_ident(cmd->payload);
2269 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2270 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2272 silc_server_packet_send(server, entry->connection,
2273 SILC_PACKET_COMMAND, cmd->packet->flags,
2274 tmpbuf->data, tmpbuf->len, TRUE);
2276 /* Reprocess this packet after received reply from router */
2277 silc_server_command_pending(server, SILC_COMMAND_INFO,
2278 silc_command_get_ident(cmd->payload),
2279 silc_server_command_destructor,
2280 silc_server_command_info,
2281 silc_server_command_dup(cmd));
2282 cmd->pending = TRUE;
2283 silc_command_set_ident(cmd->payload, old_ident);
2284 silc_buffer_free(tmpbuf);
2288 if (!entry && !cmd->pending && !server->standalone) {
2289 /* Send to the primary router */
2291 unsigned short old_ident;
2293 old_ident = silc_command_get_ident(cmd->payload);
2294 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2295 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2297 silc_server_packet_send(server, server->router->connection,
2298 SILC_PACKET_COMMAND, cmd->packet->flags,
2299 tmpbuf->data, tmpbuf->len, TRUE);
2301 /* Reprocess this packet after received reply from router */
2302 silc_server_command_pending(server, SILC_COMMAND_INFO,
2303 silc_command_get_ident(cmd->payload),
2304 silc_server_command_destructor,
2305 silc_server_command_info,
2306 silc_server_command_dup(cmd));
2307 cmd->pending = TRUE;
2308 silc_command_set_ident(cmd->payload, old_ident);
2309 silc_buffer_free(tmpbuf);
2315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2316 SILC_STATUS_ERR_NO_SUCH_SERVER);
2320 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2322 server_info = entry->server_info;
2323 server_name = dest_server;
2325 /* Send the reply */
2326 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2327 SILC_STATUS_OK, ident, 3,
2328 2, idp->data, idp->len,
2330 strlen(server_name),
2332 strlen(server_info));
2333 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2334 packet->data, packet->len, FALSE);
2336 silc_buffer_free(packet);
2337 silc_buffer_free(idp);
2340 silc_server_command_free(cmd);
2343 /* Server side of command PING. This just replies to the ping. */
2345 SILC_SERVER_CMD_FUNC(ping)
2347 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2348 SilcServer server = cmd->server;
2353 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2356 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2358 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2359 SILC_STATUS_ERR_NO_SERVER_ID);
2362 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2366 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2367 /* Send our reply */
2368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2371 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2372 SILC_STATUS_ERR_NO_SUCH_SERVER);
2379 silc_server_command_free(cmd);
2382 /* Internal routine to join channel. The channel sent to this function
2383 has been either created or resolved from ID lists. This joins the sent
2384 client to the channel. */
2386 static void silc_server_command_join_channel(SilcServer server,
2387 SilcServerCommandContext cmd,
2388 SilcChannelEntry channel,
2389 SilcClientID *client_id,
2393 SilcSocketConnection sock = cmd->sock;
2395 unsigned int tmp_len, user_count;
2396 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2397 SilcClientEntry client;
2398 SilcChannelClientEntry chl;
2399 SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
2400 unsigned short ident = silc_command_get_ident(cmd->payload);
2402 SILC_LOG_DEBUG(("Start"));
2407 /* Get passphrase */
2408 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2410 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2411 memcpy(passphrase, tmp, tmp_len);
2415 * Check channel modes
2418 /* Check invite list if channel is invite-only channel */
2419 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2420 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2421 /* Invite list is specified. Check whether client is invited in the
2422 list. If not, then check whether it has been invited otherwise. */
2425 /* XXX client must be invited to be able to join the channel */
2429 /* Check ban list if set */
2430 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2434 /* Check the channel passphrase if set. */
2435 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2436 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
2437 strlen(channel->mode_data.passphrase))) {
2438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2439 SILC_STATUS_ERR_BAD_PASSWORD);
2444 /* Check user count limit if set. */
2445 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2446 if (silc_list_count(channel->user_list) + 1 >
2447 channel->mode_data.user_limit) {
2448 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2449 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2455 * Client is allowed to join to the channel. Make it happen.
2458 /* Get the client entry */
2459 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2460 client = (SilcClientEntry)sock->user_data;
2462 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2465 /* XXX actually this is useless since router finds always cell's
2466 local clients from its local lists. */
2467 client = silc_idlist_find_client_by_id(server->global_list, client_id,
2474 /* Check whether the client already is on the channel */
2475 if (silc_server_client_on_channel(client, channel)) {
2476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2477 SILC_STATUS_ERR_USER_ON_CHANNEL);
2481 /* Generate new channel key as protocol dictates */
2482 if ((!created && silc_list_count(channel->user_list) > 0) ||
2483 !channel->channel_key)
2484 silc_server_create_channel_key(server, channel, 0);
2486 /* Send the channel key. This is broadcasted to the channel but is not
2487 sent to the client who is joining to the channel. */
2488 silc_server_send_channel_key(server, NULL, channel,
2489 server->server_type == SILC_ROUTER ?
2490 FALSE : !server->standalone);
2492 /* Join the client to the channel by adding it to channel's user list.
2493 Add also the channel to client entry's channels list for fast cross-
2495 chl = silc_calloc(1, sizeof(*chl));
2497 chl->client = client;
2498 chl->channel = channel;
2499 silc_list_add(channel->user_list, chl);
2500 silc_list_add(client->channels, chl);
2502 /* Get users on the channel */
2503 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2506 /* Encode Client ID Payload of the original client who wants to join */
2507 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2509 /* Encode command reply packet */
2510 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2511 SILC_PUT32_MSB(channel->mode, mode);
2512 SILC_PUT32_MSB(created, tmp2);
2513 SILC_PUT32_MSB(user_count, tmp3);
2514 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2515 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2516 strlen(channel->channel_key->
2518 channel->channel_key->cipher->name,
2519 channel->key_len / 8, channel->key);
2521 if (!channel->topic) {
2523 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2524 SILC_STATUS_OK, ident, 9,
2525 2, channel->channel_name,
2526 strlen(channel->channel_name),
2527 3, chidp->data, chidp->len,
2528 4, clidp->data, clidp->len,
2531 7, keyp->data, keyp->len,
2533 13, user_list->data, user_list->len,
2534 14, mode_list->data,
2538 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2539 SILC_STATUS_OK, ident, 10,
2540 2, channel->channel_name,
2541 strlen(channel->channel_name),
2542 3, chidp->data, chidp->len,
2543 4, clidp->data, clidp->len,
2546 7, keyp->data, keyp->len,
2548 strlen(channel->topic),
2550 13, user_list->data, user_list->len,
2551 14, mode_list->data,
2555 /* Send command reply */
2556 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2557 reply->data, reply->len, FALSE);
2559 if (!cmd->pending) {
2560 /* Send JOIN notify to locally connected clients on the channel */
2561 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2562 SILC_NOTIFY_TYPE_JOIN, 2,
2563 clidp->data, clidp->len,
2564 chidp->data, chidp->len);
2566 /* Send JOIN notify packet to our primary router */
2567 if (!server->standalone)
2568 silc_server_send_notify_join(server, server->router->connection,
2569 server->server_type == SILC_ROUTER ?
2570 TRUE : FALSE, channel, client->id,
2571 SILC_ID_CLIENT_LEN);
2574 silc_buffer_free(reply);
2575 silc_buffer_free(clidp);
2576 silc_buffer_free(chidp);
2577 silc_buffer_free(keyp);
2578 silc_buffer_free(user_list);
2579 silc_buffer_free(mode_list);
2583 silc_free(passphrase);
2586 /* Server side of command JOIN. Joins client into requested channel. If
2587 the channel does not exist it will be created. */
2589 SILC_SERVER_CMD_FUNC(join)
2591 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2592 SilcServer server = cmd->server;
2594 char *tmp, *channel_name = NULL, *cipher, *hmac;
2595 SilcChannelEntry channel;
2596 unsigned int umode = 0;
2597 int created = FALSE;
2598 SilcClientID *client_id;
2600 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2602 /* Get channel name */
2603 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2605 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2606 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2611 if (strlen(channel_name) > 256)
2612 channel_name[255] = '\0';
2614 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2616 SILC_STATUS_ERR_BAD_CHANNEL);
2617 silc_free(channel_name);
2621 /* Get Client ID of the client who is joining to the channel */
2622 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2624 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2625 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2628 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2630 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2631 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2635 /* Get cipher and hmac name */
2636 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2637 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2639 /* See if the channel exists */
2640 channel = silc_idlist_find_channel_by_name(server->local_list,
2641 channel_name, NULL);
2643 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2644 /* If this is coming from client the Client ID in the command packet must
2645 be same as the client's ID. */
2646 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2647 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2648 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2649 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2650 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2656 /* Channel not found */
2658 /* If we are standalone server we don't have a router, we just create
2659 the channel by ourselves. */
2660 if (server->standalone) {
2661 channel = silc_server_create_new_channel(server, server->id, cipher,
2662 hmac, channel_name, TRUE);
2663 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2668 /* The channel does not exist on our server. If we are normal server
2669 we will send JOIN command to our router which will handle the
2670 joining procedure (either creates the channel if it doesn't exist
2671 or joins the client to it). */
2672 if (server->server_type == SILC_SERVER) {
2674 unsigned short old_ident;
2676 old_ident = silc_command_get_ident(cmd->payload);
2677 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2678 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2680 /* Send JOIN command to our router */
2681 silc_server_packet_send(server, (SilcSocketConnection)
2682 server->router->connection,
2683 SILC_PACKET_COMMAND, cmd->packet->flags,
2684 tmpbuf->data, tmpbuf->len, TRUE);
2686 /* Reprocess this packet after received reply from router */
2687 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2688 silc_command_get_ident(cmd->payload),
2689 silc_server_command_destructor,
2690 silc_server_command_join,
2691 silc_server_command_dup(cmd));
2692 cmd->pending = TRUE;
2696 /* We are router and the channel does not seem exist so we will check
2697 our global list as well for the channel. */
2698 channel = silc_idlist_find_channel_by_name(server->global_list,
2699 channel_name, NULL);
2701 /* Channel really does not exist, create it */
2702 channel = silc_server_create_new_channel(server, server->id, cipher,
2703 hmac, channel_name, TRUE);
2704 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2711 /* Channel not found */
2713 /* If the command came from router and/or we are normal server then
2714 something went wrong with the joining as the channel was not found.
2715 We can't do anything else but ignore this. */
2716 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2717 server->server_type == SILC_SERVER)
2720 /* We are router and the channel does not seem exist so we will check
2721 our global list as well for the channel. */
2722 channel = silc_idlist_find_channel_by_name(server->global_list,
2723 channel_name, NULL);
2725 /* Channel really does not exist, create it */
2726 channel = silc_server_create_new_channel(server, server->id, cipher,
2727 hmac, channel_name, TRUE);
2728 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2734 /* If the channel does not have global users and is also empty it means the
2735 channel was created globally (by our router) and the client will be the
2736 channel founder and operator. */
2737 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2738 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2739 created = TRUE; /* Created globally by our router */
2742 /* Join to the channel */
2743 silc_server_command_join_channel(server, cmd, channel, client_id,
2746 silc_free(client_id);
2749 silc_server_command_free(cmd);
2752 /* Server side of command MOTD. Sends server's current "message of the
2753 day" to the client. */
2755 SILC_SERVER_CMD_FUNC(motd)
2757 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2758 SilcServer server = cmd->server;
2762 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2764 /* XXX show currently only our motd */
2766 if (server->config && server->config->motd &&
2767 server->config->motd->motd_file) {
2770 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2775 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2781 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2786 silc_server_command_free(cmd);
2789 /* Server side of command UMODE. Client can use this command to set/unset
2790 user mode. Client actually cannot set itself to be as server/router
2791 operator so this can be used only to unset the modes. */
2793 SILC_SERVER_CMD_FUNC(umode)
2795 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2796 SilcServer server = cmd->server;
2797 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2799 unsigned char *tmp_mask;
2801 unsigned short ident = silc_command_get_ident(cmd->payload);
2803 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2806 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
2808 /* Get the client's mode mask */
2809 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2812 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2815 SILC_GET32_MSB(mask, tmp_mask);
2821 if (mask & SILC_UMODE_SERVER_OPERATOR) {
2822 /* Cannot operator mode */
2823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2824 SILC_STATUS_ERR_PERM_DENIED);
2827 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
2828 /* Remove the server operator rights */
2829 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
2832 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
2833 /* Cannot operator mode */
2834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2835 SILC_STATUS_ERR_PERM_DENIED);
2838 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
2839 /* Remove the router operator rights */
2840 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
2843 /* Send UMODE change to primary router */
2844 if (!server->standalone)
2845 silc_server_send_notify_umode(server, server->router->connection, TRUE,
2846 client->id, SILC_ID_CLIENT_LEN,
2849 /* Send command reply to sender */
2850 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
2851 SILC_STATUS_OK, ident, 1,
2853 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2854 packet->data, packet->len, FALSE);
2855 silc_buffer_free(packet);
2858 silc_server_command_free(cmd);
2861 /* Checks that client has rights to add or remove channel modes. If any
2862 of the checks fails FALSE is returned. */
2864 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2865 SilcChannelClientEntry client,
2868 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2869 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2871 /* Check whether has rights to change anything */
2872 if (!is_op && !is_fo)
2875 /* Check whether has rights to change everything */
2879 /* We know that client is channel operator, check that they are not
2880 changing anything that requires channel founder rights. Rest of the
2881 modes are available automatically for channel operator. */
2883 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2884 if (is_op && !is_fo)
2887 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2888 if (is_op && !is_fo)
2893 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2894 if (is_op && !is_fo)
2897 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2898 if (is_op && !is_fo)
2903 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2904 if (is_op && !is_fo)
2907 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2908 if (is_op && !is_fo)
2916 /* Server side command of CMODE. Changes channel mode */
2918 SILC_SERVER_CMD_FUNC(cmode)
2920 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2921 SilcServer server = cmd->server;
2922 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2923 SilcChannelID *channel_id;
2924 SilcChannelEntry channel;
2925 SilcChannelClientEntry chl;
2926 SilcBuffer packet, cidp;
2927 unsigned char *tmp, *tmp_id, *tmp_mask;
2928 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2929 unsigned short ident = silc_command_get_ident(cmd->payload);
2931 SILC_LOG_DEBUG(("Start"));
2933 argc = silc_argument_get_arg_num(cmd->args);
2935 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2936 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2940 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2941 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2945 /* Get Channel ID */
2946 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2949 SILC_STATUS_ERR_NO_CHANNEL_ID);
2952 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2955 SILC_STATUS_ERR_NO_CHANNEL_ID);
2959 /* Get the channel mode mask */
2960 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2963 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2966 SILC_GET32_MSB(mode_mask, tmp_mask);
2968 /* Get channel entry */
2969 channel = silc_idlist_find_channel_by_id(server->local_list,
2972 channel = silc_idlist_find_channel_by_id(server->global_list,
2975 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2976 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2981 /* Check whether this client is on the channel */
2982 if (!silc_server_client_on_channel(client, channel)) {
2983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2984 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2988 /* Get entry to the channel user list */
2989 silc_list_start(channel->user_list);
2990 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2991 if (chl->client == client)
2994 /* Check that client has rights to change any requested channel modes */
2995 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2996 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2997 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3002 * Check the modes. Modes that requires nothing special operation are
3006 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3007 /* Channel uses private keys to protect traffic. Client(s) has set the
3008 key locally they want to use, server does not know that key. */
3009 /* Nothing interesting to do here now */
3011 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3012 /* The mode is removed and we need to generate and distribute
3013 new channel key. Clients are not using private channel keys
3014 anymore after this. */
3016 /* XXX Duplicated code, make own function for this!! LEAVE uses this
3019 /* Re-generate channel key */
3020 silc_server_create_channel_key(server, channel, 0);
3022 /* Encode channel key payload to be distributed on the channel */
3024 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3025 strlen(channel->channel_key->
3027 channel->channel_key->cipher->name,
3028 channel->key_len / 8, channel->key);
3030 /* If we are normal server then we will send it to our router. If we
3031 are router we will send it to all local servers that has clients on
3033 if (server->server_type == SILC_SERVER) {
3034 if (!server->standalone)
3035 silc_server_packet_send(server,
3036 cmd->server->router->connection,
3037 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3043 /* Send to locally connected clients on the channel */
3044 silc_server_packet_send_local_channel(server, channel,
3045 SILC_PACKET_CHANNEL_KEY, 0,
3046 packet->data, packet->len, FALSE);
3047 silc_buffer_free(packet);
3051 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3052 /* User limit is set on channel */
3053 unsigned int user_limit;
3055 /* Get user limit */
3056 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3058 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3059 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3060 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3064 SILC_GET32_MSB(user_limit, tmp);
3065 channel->mode_data.user_limit = user_limit;
3068 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3069 /* User limit mode is unset. Remove user limit */
3070 channel->mode_data.user_limit = 0;
3073 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3074 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3075 /* Passphrase has been set to channel */
3077 /* Get the passphrase */
3078 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3080 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3081 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3085 /* Save the passphrase */
3086 channel->mode_data.passphrase = strdup(tmp);
3089 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3090 /* Passphrase mode is unset. remove the passphrase */
3091 if (channel->mode_data.passphrase) {
3092 silc_free(channel->mode_data.passphrase);
3093 channel->mode_data.passphrase = NULL;
3098 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
3099 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
3100 /* Ban list is specified for channel */
3103 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
3105 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3106 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3110 /* XXX check that channel founder is not banned */
3112 /* Save the ban list */
3113 channel->mode_data.ban_list = strdup(tmp);
3116 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
3117 /* Ban mode is unset. Remove the entire ban list */
3118 if (channel->mode_data.ban_list) {
3119 silc_free(channel->mode_data.ban_list);
3120 channel->mode_data.ban_list = NULL;
3125 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
3126 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
3127 /* Invite list is specified for channel */
3129 /* Get invite list */
3130 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
3132 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3133 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3137 /* Save the invite linst */
3138 channel->mode_data.invite_list = strdup(tmp);
3141 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
3142 /* Invite list mode is unset. Remove the entire invite list */
3143 if (channel->mode_data.invite_list) {
3144 silc_free(channel->mode_data.invite_list);
3145 channel->mode_data.invite_list = NULL;
3150 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3151 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3152 /* Cipher to use protect the traffic */
3153 unsigned int key_len;
3156 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
3158 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3159 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3163 /* XXX Duplicated code, make own function for this!! */
3165 /* Delete old cipher and allocate the new one */
3166 silc_cipher_free(channel->channel_key);
3167 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
3168 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3169 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3172 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
3174 /* Re-generate channel key */
3175 silc_server_create_channel_key(server, channel, key_len);
3177 /* Encode channel key payload to be distributed on the channel */
3179 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3180 strlen(channel->channel_key->
3182 channel->channel_key->cipher->name,
3183 channel->key_len / 8, channel->key);
3185 /* If we are normal server then we will send it to our router. If we
3186 are router we will send it to all local servers that has clients on
3188 if (server->server_type == SILC_SERVER) {
3189 if (!server->standalone)
3190 silc_server_packet_send(server,
3191 cmd->server->router->connection,
3192 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3198 /* Send to locally connected clients on the channel */
3199 silc_server_packet_send_local_channel(server, channel,
3200 SILC_PACKET_CHANNEL_KEY, 0,
3201 packet->data, packet->len, FALSE);
3202 silc_buffer_free(packet);
3205 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3206 /* Cipher mode is unset. Remove the cipher and revert back to
3209 if (channel->mode_data.cipher) {
3210 silc_free(channel->mode_data.cipher);
3211 channel->mode_data.cipher = NULL;
3212 channel->mode_data.key_len = 0;
3215 /* Generate new cipher and key for the channel */
3217 /* XXX Duplicated code, make own function for this!! */
3219 /* Delete old cipher and allocate default one */
3220 silc_cipher_free(channel->channel_key);
3221 if (!channel->cipher)
3222 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
3224 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
3225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3226 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3231 /* Re-generate channel key */
3232 silc_server_create_channel_key(server, channel, 0);
3234 /* Encode channel key payload to be distributed on the channel */
3236 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3237 strlen(channel->channel_key->
3239 channel->channel_key->cipher->name,
3240 channel->key_len / 8, channel->key);
3242 /* If we are normal server then we will send it to our router. If we
3243 are router we will send it to all local servers that has clients on
3245 if (server->server_type == SILC_SERVER) {
3246 if (!server->standalone)
3247 silc_server_packet_send(server,
3248 cmd->server->router->connection,
3249 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3255 /* Send to locally connected clients on the channel */
3256 silc_server_packet_send_local_channel(server, channel,
3257 SILC_PACKET_CHANNEL_KEY, 0,
3258 packet->data, packet->len, FALSE);
3259 silc_buffer_free(packet);
3263 /* Finally, set the mode */
3264 channel->mode = mode_mask;
3266 /* Send CMODE_CHANGE notify */
3267 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3268 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3269 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
3270 cidp->data, cidp->len,
3273 /* Set CMODE notify type to network */
3274 if (!server->standalone)
3275 silc_server_send_notify_cmode(server, server->router->connection,
3276 server->server_type == SILC_ROUTER ?
3277 TRUE : FALSE, channel,
3278 mode_mask, client->id, SILC_ID_CLIENT_LEN);
3280 /* Send command reply to sender */
3281 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3282 SILC_STATUS_OK, ident, 1,
3284 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3285 packet->data, packet->len, FALSE);
3287 silc_buffer_free(packet);
3288 silc_free(channel_id);
3292 silc_server_command_free(cmd);
3295 /* Server side of CUMODE command. Changes client's mode on a channel. */
3297 SILC_SERVER_CMD_FUNC(cumode)
3299 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3300 SilcServer server = cmd->server;
3301 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3302 SilcChannelID *channel_id;
3303 SilcClientID *client_id;
3304 SilcChannelEntry channel;
3305 SilcClientEntry target_client;
3306 SilcChannelClientEntry chl;
3307 SilcBuffer packet, idp;
3308 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3309 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3311 unsigned short ident = silc_command_get_ident(cmd->payload);
3313 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3315 /* Get Channel ID */
3316 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3319 SILC_STATUS_ERR_NO_CHANNEL_ID);
3322 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3325 SILC_STATUS_ERR_NO_CHANNEL_ID);
3329 /* Get channel entry */
3330 channel = silc_idlist_find_channel_by_id(server->local_list,
3333 channel = silc_idlist_find_channel_by_id(server->global_list,
3336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3337 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3342 /* Check whether sender is on the channel */
3343 if (!silc_server_client_on_channel(client, channel)) {
3344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3345 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3349 /* Check that client has rights to change other's rights */
3350 silc_list_start(channel->user_list);
3351 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3352 if (chl->client == client) {
3353 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3354 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3355 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3356 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3360 sender_mask = chl->mode;
3365 /* Get the target client's channel mode mask */
3366 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3369 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3372 SILC_GET32_MSB(target_mask, tmp_mask);
3374 /* Get target Client ID */
3375 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3377 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3378 SILC_STATUS_ERR_NO_CLIENT_ID);
3381 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3384 SILC_STATUS_ERR_NO_CLIENT_ID);
3388 /* Get target client's entry */
3389 target_client = silc_idlist_find_client_by_id(server->local_list,
3391 if (!target_client) {
3392 target_client = silc_idlist_find_client_by_id(server->global_list,
3396 /* Check whether target client is on the channel */
3397 if (!silc_server_client_on_channel(target_client, channel)) {
3398 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3399 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3403 /* Get entry to the channel user list */
3404 silc_list_start(channel->user_list);
3405 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3406 if (chl->client == target_client)
3413 /* If the target client is founder, no one else can change their mode
3415 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3416 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3417 SILC_STATUS_ERR_NOT_YOU);
3421 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3422 /* Cannot promote anyone to channel founder */
3423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3424 SILC_STATUS_ERR_NOT_YOU);
3427 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3428 if (target_client == client) {
3429 /* Remove channel founder rights from itself */
3430 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3433 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3434 SILC_STATUS_ERR_NOT_YOU);
3440 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3441 /* Promote to operator */
3442 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3443 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3447 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3448 /* Demote to normal user */
3449 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3454 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3456 /* Send notify to channel, notify only if mode was actually changed. */
3458 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3459 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3460 idp->data, idp->len,
3464 /* Set CUMODE notify type to network */
3465 if (!server->standalone)
3466 silc_server_send_notify_cumode(server, server->router->connection,
3467 server->server_type == SILC_ROUTER ?
3468 TRUE : FALSE, channel,
3469 target_mask, client->id,
3472 SILC_ID_CLIENT_LEN);
3475 /* Send command reply to sender */
3476 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3477 SILC_STATUS_OK, ident, 2,
3479 3, tmp_id, tmp_len);
3480 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3481 packet->data, packet->len, FALSE);
3483 silc_buffer_free(packet);
3484 silc_free(channel_id);
3485 silc_free(client_id);
3486 silc_buffer_free(idp);
3489 silc_server_command_free(cmd);
3492 /* Server side of KICK command. Kicks client out of channel. */
3494 SILC_SERVER_CMD_FUNC(kick)
3496 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3497 SilcServer server = cmd->server;
3498 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3499 SilcClientEntry target_client;
3500 SilcChannelID *channel_id;
3501 SilcClientID *client_id;
3502 SilcChannelEntry channel;
3503 SilcChannelClientEntry chl;
3505 unsigned int tmp_len;
3506 unsigned char *tmp, *comment;
3508 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3510 /* Get Channel ID */
3511 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3513 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3514 SILC_STATUS_ERR_NO_CHANNEL_ID);
3517 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3520 SILC_STATUS_ERR_NO_CHANNEL_ID);
3524 /* Get channel entry */
3525 channel = silc_idlist_find_channel_by_id(server->local_list,
3528 channel = silc_idlist_find_channel_by_id(server->local_list,
3531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3532 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3537 /* Check whether sender is on the channel */
3538 if (!silc_server_client_on_channel(client, channel)) {
3539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3540 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3544 /* Check that the kicker is channel operator or channel founder */
3545 silc_list_start(channel->user_list);
3546 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3547 if (chl->client == client) {
3548 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3549 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3550 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3557 /* Get target Client ID */
3558 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3561 SILC_STATUS_ERR_NO_CLIENT_ID);
3564 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3567 SILC_STATUS_ERR_NO_CLIENT_ID);
3571 /* Get target client's entry */
3572 target_client = silc_idlist_find_client_by_id(server->local_list,
3574 if (!target_client) {
3575 target_client = silc_idlist_find_client_by_id(server->global_list,
3579 /* Check that the target client is not channel founder. Channel founder
3580 cannot be kicked from the channel. */
3581 silc_list_start(channel->user_list);
3582 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3583 if (chl->client == target_client) {
3584 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3585 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3586 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3593 /* Check whether target client is on the channel */
3594 if (!silc_server_client_on_channel(target_client, channel)) {
3595 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3596 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3602 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3606 /* Send command reply to sender */
3607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3610 /* Send KICKED notify to local clients on the channel */
3611 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3612 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3613 SILC_NOTIFY_TYPE_KICKED,
3615 idp->data, idp->len,
3616 comment, comment ? strlen(comment) : 0);
3617 silc_buffer_free(idp);
3619 /* Remove the client from the channel. If the channel does not exist
3620 after removing the client then the client kicked itself off the channel
3621 and we don't have to send anything after that. */
3622 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3623 target_client, FALSE))
3626 /* Send KICKED notify to primary route */
3627 if (!server->standalone)
3628 silc_server_send_notify_kicked(server, server->router->connection,
3629 server->server_type == SILC_ROUTER ?
3630 TRUE : FALSE, channel,
3631 target_client->id, SILC_ID_CLIENT_LEN,
3634 /* Re-generate channel key */
3635 silc_server_create_channel_key(server, channel, 0);
3637 /* Send the channel key to the channel. The key of course is not sent
3638 to the client who was kicked off the channel. */
3639 silc_server_send_channel_key(server, target_client->connection, channel,
3640 server->server_type == SILC_ROUTER ?
3641 FALSE : !server->standalone);
3644 silc_server_command_free(cmd);
3647 /* Server side of OPER command. Client uses this comand to obtain server
3648 operator privileges to this server/router. */
3650 SILC_SERVER_CMD_FUNC(oper)
3652 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3653 SilcServer server = cmd->server;
3654 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3655 unsigned char *username, *auth;
3656 unsigned int tmp_len;
3657 SilcServerConfigSectionAdminConnection *admin;
3658 SilcIDListData idata = (SilcIDListData)client;
3660 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
3662 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3665 /* Get the username */
3666 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3669 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3673 /* Get the admin configuration */
3674 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3675 username, client->nickname);
3677 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3678 username, client->nickname);
3680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3681 SILC_STATUS_ERR_AUTH_FAILED);
3686 /* Get the authentication payload */
3687 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3690 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3694 /* Verify the authentication data */
3695 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3696 admin->auth_data, admin->auth_data_len,
3697 idata->hash, client->id, SILC_ID_CLIENT)) {
3698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3699 SILC_STATUS_ERR_AUTH_FAILED);
3703 /* Client is now server operator */
3704 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3706 /* Send UMODE change to primary router */
3707 if (!server->standalone)
3708 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3709 client->id, SILC_ID_CLIENT_LEN,
3712 /* Send reply to the sender */
3713 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3717 silc_server_command_free(cmd);
3720 /* Server side of SILCOPER command. Client uses this comand to obtain router
3721 operator privileges to this router. */
3723 SILC_SERVER_CMD_FUNC(silcoper)
3725 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3726 SilcServer server = cmd->server;
3727 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3728 unsigned char *username, *auth;
3729 unsigned int tmp_len;
3730 SilcServerConfigSectionAdminConnection *admin;
3731 SilcIDListData idata = (SilcIDListData)client;
3733 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
3735 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3738 /* Get the username */
3739 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3741 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3742 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3746 /* Get the admin configuration */
3747 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3748 username, client->nickname);
3750 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3751 username, client->nickname);
3753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3754 SILC_STATUS_ERR_AUTH_FAILED);
3759 /* Get the authentication payload */
3760 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3763 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3767 /* Verify the authentication data */
3768 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3769 admin->auth_data, admin->auth_data_len,
3770 idata->hash, client->id, SILC_ID_CLIENT)) {
3771 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3772 SILC_STATUS_ERR_AUTH_FAILED);
3776 /* Client is now router operator */
3777 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
3779 /* Send UMODE change to primary router */
3780 if (!server->standalone)
3781 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3782 client->id, SILC_ID_CLIENT_LEN,
3785 /* Send reply to the sender */
3786 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3790 silc_server_command_free(cmd);
3793 /* Server side command of CONNECT. Connects us to the specified remote
3794 server or router. */
3796 SILC_SERVER_CMD_FUNC(connect)
3798 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3799 SilcServer server = cmd->server;
3800 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3801 unsigned char *tmp, *host;
3802 unsigned int tmp_len;
3803 unsigned int port = SILC_PORT;
3805 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
3807 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3810 /* Check whether client has the permissions. */
3811 if (client->mode == SILC_UMODE_NONE) {
3812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3813 SILC_STATUS_ERR_NO_SERVER_PRIV);
3817 if (server->server_type == SILC_ROUTER &&
3818 client->mode & SILC_UMODE_SERVER_OPERATOR) {
3819 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3820 SILC_STATUS_ERR_NO_ROUTER_PRIV);
3824 /* Get the remote server */
3825 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3827 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3828 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3833 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3835 SILC_GET32_MSB(port, tmp);
3837 /* Create the connection. It is done with timeout and is async. */
3838 silc_server_create_connection(server, host, port);
3840 /* Send reply to the sender */
3841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3845 silc_server_command_free(cmd);
3848 SILC_SERVER_CMD_FUNC(restart)
3852 /* Server side command of CLOSE. Closes connection to a specified server. */
3854 SILC_SERVER_CMD_FUNC(close)
3856 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3857 SilcServer server = cmd->server;
3858 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3859 SilcServerEntry server_entry;
3860 SilcSocketConnection sock;
3862 unsigned int tmp_len;
3863 unsigned char *name;
3864 unsigned int port = SILC_PORT;
3866 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3868 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3871 /* Check whether client has the permissions. */
3872 if (client->mode == SILC_UMODE_NONE) {
3873 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3874 SILC_STATUS_ERR_NO_SERVER_PRIV);
3878 /* Get the remote server */
3879 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3881 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3882 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3887 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3889 SILC_GET32_MSB(port, tmp);
3891 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3893 if (!server_entry) {
3894 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3895 SILC_STATUS_ERR_NO_SERVER_ID);
3899 /* Send reply to the sender */
3900 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3903 /* Close the connection to the server */
3904 sock = (SilcSocketConnection)server_entry->connection;
3905 silc_server_free_sock_user_data(server, sock);
3906 silc_server_close_connection(server, sock);
3909 silc_server_command_free(cmd);
3912 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3913 active connections. */
3915 SILC_SERVER_CMD_FUNC(shutdown)
3917 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3918 SilcServer server = cmd->server;
3919 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3921 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3923 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3926 /* Check whether client has the permission. */
3927 if (client->mode == SILC_UMODE_NONE) {
3928 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3929 SILC_STATUS_ERR_NO_SERVER_PRIV);
3933 /* Send reply to the sender */
3934 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3937 /* Then, gracefully, or not, bring the server down. */
3938 silc_server_stop(server);
3942 silc_server_command_free(cmd);
3945 /* Server side command of LEAVE. Removes client from a channel. */
3947 SILC_SERVER_CMD_FUNC(leave)
3949 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3950 SilcServer server = cmd->server;
3951 SilcSocketConnection sock = cmd->sock;
3952 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3954 SilcChannelEntry channel;
3956 unsigned int i, len;
3959 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3961 /* Get Channel ID */
3962 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3964 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3965 SILC_STATUS_ERR_NO_CHANNEL_ID);
3968 id = silc_id_payload_parse_id(tmp, len);
3970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3971 SILC_STATUS_ERR_NO_CHANNEL_ID);
3975 /* Get channel entry */
3976 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3978 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3980 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3981 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3986 /* Check whether this client is on the channel */
3987 if (!silc_server_client_on_channel(id_entry, channel)) {
3988 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3989 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3993 /* Notify routers that they should remove this client from their list
3994 of clients on the channel. Send LEAVE notify type. */
3995 if (!server->standalone)
3996 silc_server_send_notify_leave(server, server->router->connection,
3997 server->server_type == SILC_ROUTER ?
3998 TRUE : FALSE, channel, id_entry->id,
3999 SILC_ID_CLIENT_LEN);
4001 /* Remove client from channel */
4002 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4007 /* If the channel does not exist anymore we won't send anything */
4011 /* Re-generate channel key */
4012 silc_server_create_channel_key(server, channel, 0);
4014 /* Encode channel key payload to be distributed on the channel */
4016 silc_channel_key_payload_encode(len, tmp,
4017 strlen(channel->channel_key->cipher->name),
4018 channel->channel_key->cipher->name,
4019 channel->key_len / 8, channel->key);
4021 /* If we are normal server then we will send it to our router. If we
4022 are router we will send it to all local servers that has clients on
4024 if (server->server_type == SILC_SERVER) {
4025 if (!server->standalone)
4026 silc_server_packet_send(server,
4027 cmd->server->router->connection,
4028 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
4029 packet->len, FALSE);
4034 /* Send to locally connected clients on the channel */
4035 silc_server_packet_send_local_channel(server, channel,
4036 SILC_PACKET_CHANNEL_KEY, 0,
4037 packet->data, packet->len, FALSE);
4039 silc_buffer_free(packet);
4043 silc_server_command_free(cmd);
4046 /* Server side of command USERS. Resolves clients and their USERS currently
4047 joined on the requested channel. The list of Client ID's and their modes
4048 on the channel is sent back. */
4050 SILC_SERVER_CMD_FUNC(users)
4052 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4053 SilcServer server = cmd->server;
4054 SilcChannelEntry channel;
4057 unsigned char *channel_id;
4058 unsigned int channel_id_len;
4059 SilcBuffer client_id_list;
4060 SilcBuffer client_mode_list;
4061 unsigned char lc[4];
4062 unsigned int list_count = 0;
4063 unsigned short ident = silc_command_get_ident(cmd->payload);
4065 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4067 /* Get Channel ID */
4068 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4070 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4071 SILC_STATUS_ERR_NO_CHANNEL_ID);
4074 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4076 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4077 SILC_STATUS_ERR_NO_CHANNEL_ID);
4081 /* If we are server and we don't know about this channel we will send
4082 the command to our router. If we know about the channel then we also
4083 have the list of users already. */
4084 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4086 if (server->server_type == SILC_SERVER && !server->standalone &&
4090 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4091 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4093 /* Send USERS command */
4094 silc_server_packet_send(server, server->router->connection,
4095 SILC_PACKET_COMMAND, cmd->packet->flags,
4096 tmpbuf->data, tmpbuf->len, TRUE);
4098 /* Reprocess this packet after received reply */
4099 silc_server_command_pending(server, SILC_COMMAND_USERS,
4100 silc_command_get_ident(cmd->payload),
4101 silc_server_command_destructor,
4102 silc_server_command_users,
4103 silc_server_command_dup(cmd));
4104 cmd->pending = TRUE;
4105 silc_command_set_ident(cmd->payload, ident);
4107 silc_buffer_free(tmpbuf);
4112 /* We are router and we will check the global list as well. */
4113 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4115 /* Channel really does not exist */
4116 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4117 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4122 /* Get the users list */
4123 silc_server_get_users_on_channel(server, channel, &client_id_list,
4124 &client_mode_list, &list_count);
4127 SILC_PUT32_MSB(list_count, lc);
4130 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4131 SILC_STATUS_OK, ident, 4,
4132 2, channel_id, channel_id_len,
4134 4, client_id_list->data,
4135 client_id_list->len,
4136 5, client_mode_list->data,
4137 client_mode_list->len);
4138 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4139 packet->data, packet->len, FALSE);
4141 silc_buffer_free(packet);
4142 silc_buffer_free(client_id_list);
4143 silc_buffer_free(client_mode_list);
4147 silc_server_command_free(cmd);