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,
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(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
66 SILC_SERVER_CMD(close, CLOSE,
67 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
68 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
70 SILC_SERVER_CMD(silcoper, SILCOPER,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
72 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
73 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
78 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
80 uint32 _argc = silc_argument_get_arg_num(cmd->args); \
82 SILC_LOG_DEBUG(("Start")); \
85 silc_server_command_send_status_reply(cmd, command, \
86 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
87 silc_server_command_free(cmd); \
91 silc_server_command_send_status_reply(cmd, command, \
92 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
93 silc_server_command_free(cmd); \
98 /* Returns TRUE if the connection is registered. Unregistered connections
99 usually cannot send commands hence the check. */
101 static int silc_server_is_registered(SilcServer server,
102 SilcSocketConnection sock,
103 SilcServerCommandContext cmd,
106 SilcIDListData idata = (SilcIDListData)sock->user_data;
107 if (idata->registered)
110 silc_server_command_send_status_reply(cmd, command,
111 SILC_STATUS_ERR_NOT_REGISTERED);
112 silc_server_command_free(cmd);
116 /* Internal context to hold data when executed command with timeout. */
118 SilcServerCommandContext ctx;
119 SilcServerCommand *cmd;
120 } *SilcServerCommandTimeout;
122 /* Timeout callback to process commands with timeout for client. Client's
123 commands are always executed with timeout. */
125 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
127 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
128 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
130 /* Update access time */
131 client->last_command = time(NULL);
133 if (!(timeout->cmd->flags & SILC_CF_REG))
134 timeout->cmd->cb(timeout->ctx);
135 else if (silc_server_is_registered(timeout->ctx->server,
139 timeout->cmd->cb(timeout->ctx);
144 /* Processes received command packet. */
146 void silc_server_command_process(SilcServer server,
147 SilcSocketConnection sock,
148 SilcPacketContext *packet)
150 SilcServerCommandContext ctx;
151 SilcServerCommand *cmd;
154 /* Allocate command context. This must be free'd by the
155 command routine receiving it. */
156 ctx = silc_server_command_alloc();
157 ctx->server = server;
158 ctx->sock = silc_socket_dup(sock);
159 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
161 /* Parse the command payload in the packet */
162 ctx->payload = silc_command_payload_parse(packet->buffer);
164 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
165 silc_buffer_free(packet->buffer);
166 silc_packet_context_free(packet);
167 silc_socket_free(ctx->sock);
171 ctx->args = silc_command_get_args(ctx->payload);
173 /* Get the command */
174 command = silc_command_get(ctx->payload);
175 for (cmd = silc_command_list; cmd->cb; cmd++)
176 if (cmd->cmd == command)
180 silc_server_command_send_status_reply(ctx, command,
181 SILC_STATUS_ERR_UNKNOWN_COMMAND);
182 silc_server_command_free(ctx);
186 /* Execute client's commands always with timeout. Normally they are
187 executed with zero (0) timeout but if client is sending command more
188 frequently than once in 2 seconds, then the timeout may be 0 to 2
190 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
191 SilcClientEntry client = (SilcClientEntry)sock->user_data;
192 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
198 if (client->last_command && (time(NULL) - client->last_command) < 2) {
199 client->fast_command++;
202 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
203 client->fast_command--);
207 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
208 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
209 silc_task_register(server->timeout_queue, sock->sock,
210 silc_server_command_process_timeout,
212 2 - (time(NULL) - client->last_command), 0,
214 SILC_TASK_PRI_NORMAL);
216 silc_task_register(server->timeout_queue, sock->sock,
217 silc_server_command_process_timeout,
221 SILC_TASK_PRI_NORMAL);
225 /* Execute for server */
227 if (!(cmd->flags & SILC_CF_REG))
229 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
233 /* Allocate Command Context */
235 SilcServerCommandContext silc_server_command_alloc()
237 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
242 /* Free's the command context allocated before executing the command */
244 void silc_server_command_free(SilcServerCommandContext ctx)
247 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
249 if (ctx->users < 1) {
251 silc_command_free_payload(ctx->payload);
253 silc_packet_context_free(ctx->packet);
255 silc_socket_free(ctx->sock); /* Decrease reference counter */
260 /* Duplicate Command Context by adding reference counter. The context won't
261 be free'd untill it hits zero. */
263 SilcServerCommandContext
264 silc_server_command_dup(SilcServerCommandContext ctx)
267 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
272 /* Add new pending command to be executed when reply to a command has been
273 received. The `reply_cmd' is the command that will call the `callback'
274 with `context' when reply has been received. If `ident' is non-zero
275 the `callback' will be executed when received reply with command
276 identifier `ident'. */
278 void silc_server_command_pending(SilcServer server,
279 SilcCommand reply_cmd,
281 SilcServerPendingDestructor destructor,
282 SilcCommandCb callback,
285 SilcServerCommandPending *reply;
287 reply = silc_calloc(1, sizeof(*reply));
288 reply->reply_cmd = reply_cmd;
289 reply->ident = ident;
290 reply->context = context;
291 reply->callback = callback;
292 reply->destructor = destructor;
293 silc_dlist_add(server->pending_commands, reply);
296 /* Deletes pending command by reply command type. */
298 void silc_server_command_pending_del(SilcServer server,
299 SilcCommand reply_cmd,
302 SilcServerCommandPending *r;
304 silc_dlist_start(server->pending_commands);
305 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
306 if (r->reply_cmd == reply_cmd && r->ident == ident) {
307 silc_dlist_del(server->pending_commands, r);
313 /* Checks for pending commands and marks callbacks to be called from
314 the command reply function. Returns TRUE if there were pending command. */
316 int silc_server_command_pending_check(SilcServer server,
317 SilcServerCommandReplyContext ctx,
321 SilcServerCommandPending *r;
323 silc_dlist_start(server->pending_commands);
324 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
325 if (r->reply_cmd == command && r->ident == ident) {
326 ctx->context = r->context;
327 ctx->callback = r->callback;
328 ctx->destructor = r->destructor;
337 /* Destructor function for pending callbacks. This is called when using
338 pending commands to free the context given for the pending command. */
340 static void silc_server_command_destructor(void *context)
342 silc_server_command_free((SilcServerCommandContext)context);
345 /* Sends simple status message as command reply packet */
348 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
350 SilcCommandStatus status)
354 SILC_LOG_DEBUG(("Sending command status %d", status));
357 silc_command_reply_payload_encode_va(command, status,
358 silc_command_get_ident(cmd->payload),
360 silc_server_packet_send(cmd->server, cmd->sock,
361 SILC_PACKET_COMMAND_REPLY, 0,
362 buffer->data, buffer->len, FALSE);
363 silc_buffer_free(buffer);
366 /* Sends command status reply with one extra argument. The argument
367 type must be sent as argument. */
370 silc_server_command_send_status_data(SilcServerCommandContext cmd,
372 SilcCommandStatus status,
379 SILC_LOG_DEBUG(("Sending command status %d", status));
382 silc_command_reply_payload_encode_va(command, status,
383 silc_command_get_ident(cmd->payload),
384 1, arg_type, arg, arg_len);
385 silc_server_packet_send(cmd->server, cmd->sock,
386 SILC_PACKET_COMMAND_REPLY, 0,
387 buffer->data, buffer->len, FALSE);
388 silc_buffer_free(buffer);
391 /******************************************************************************
395 ******************************************************************************/
398 silc_server_command_whois_parse(SilcServerCommandContext cmd,
399 SilcClientID ***client_id,
400 uint32 *client_id_count,
408 uint32 argc = silc_argument_get_arg_num(cmd->args);
411 /* If client ID is in the command it must be used instead of nickname */
412 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
414 /* No ID, get the nickname@server string and parse it. */
415 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
417 if (strchr(tmp, '@')) {
418 len = strcspn(tmp, "@");
419 *nickname = silc_calloc(len + 1, sizeof(char));
420 memcpy(*nickname, tmp, len);
421 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
422 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
424 *nickname = strdup(tmp);
427 silc_server_command_send_status_reply(cmd, command,
428 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
432 /* Command includes ID, we must use that. Also check whether the command
433 has more than one ID set - take them all. */
435 *client_id = silc_calloc(1, sizeof(**client_id));
436 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
437 if ((*client_id)[0] == NULL) {
438 silc_free(*client_id);
441 *client_id_count = 1;
443 /* Take all ID's from the command packet */
445 for (k = 1, i = 1; i < argc; i++) {
446 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
448 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
449 (*client_id_count + 1));
450 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
451 if ((*client_id)[k] == NULL) {
452 /* Cleanup all and fail */
453 for (i = 0; i < *client_id_count; i++)
454 silc_free((*client_id)[i]);
455 silc_free(*client_id);
458 (*client_id_count)++;
464 /* Command includes ID, use that */
467 /* Get the max count of reply messages allowed */
468 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
478 silc_server_command_whois_check(SilcServerCommandContext cmd,
479 SilcClientEntry *clients,
480 uint32 clients_count)
482 SilcServer server = cmd->server;
484 SilcClientEntry entry;
486 for (i = 0; i < clients_count; i++) {
489 if (!entry || entry->data.registered == FALSE)
492 if (!entry->nickname || !entry->username || !entry->userinfo) {
499 old_ident = silc_command_get_ident(cmd->payload);
500 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
501 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
503 /* Send WHOIS command */
504 silc_server_packet_send(server, entry->router->connection,
505 SILC_PACKET_COMMAND, cmd->packet->flags,
506 tmpbuf->data, tmpbuf->len, TRUE);
508 /* Reprocess this packet after received reply */
509 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
510 silc_command_get_ident(cmd->payload),
511 silc_server_command_destructor,
512 silc_server_command_whois,
513 silc_server_command_dup(cmd));
516 silc_command_set_ident(cmd->payload, old_ident);
518 silc_buffer_free(tmpbuf);
527 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
528 SilcClientEntry *clients,
529 uint32 clients_count,
532 SilcServer server = cmd->server;
535 SilcBuffer packet, idp, channels;
536 SilcClientEntry entry;
537 SilcCommandStatus status;
538 uint16 ident = silc_command_get_ident(cmd->payload);
539 char nh[128], uh[128];
540 unsigned char idle[4], mode[4];
541 SilcSocketConnection hsock;
544 for (i = 0; i < clients_count; i++)
545 if (clients[i]->data.registered)
548 status = SILC_STATUS_OK;
550 status = SILC_STATUS_LIST_START;
552 for (i = 0, k = 0; i < clients_count; i++) {
555 if (entry->data.registered == FALSE) {
556 if (clients_count == 1) {
557 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
558 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
559 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
560 2, idp->data, idp->len);
561 silc_buffer_free(idp);
567 status = SILC_STATUS_LIST_ITEM;
569 if (clients_count > 1 && k == clients_count - 1)
570 status = SILC_STATUS_LIST_END;
572 if (count && k - 1 == count)
573 status = SILC_STATUS_LIST_END;
575 if (count && k - 1 > count)
578 /* Sanity check, however these should never fail. However, as
579 this sanity check has been added here they have failed. */
580 if (!entry->nickname || !entry->username || !entry->userinfo)
583 /* Send WHOIS reply */
584 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
585 tmp = silc_argument_get_first_arg(cmd->args, NULL);
587 memset(uh, 0, sizeof(uh));
588 memset(nh, 0, sizeof(nh));
589 memset(idle, 0, sizeof(idle));
591 strncat(nh, entry->nickname, strlen(entry->nickname));
592 if (!strchr(entry->nickname, '@')) {
594 len = entry->router ? strlen(entry->router->server_name) :
595 strlen(server->server_name);
596 strncat(nh, entry->router ? entry->router->server_name :
597 server->server_name, len);
600 strncat(uh, entry->username, strlen(entry->username));
601 if (!strchr(entry->username, '@')) {
603 hsock = (SilcSocketConnection)entry->connection;
604 len = strlen(hsock->hostname);
605 strncat(uh, hsock->hostname, len);
608 channels = silc_server_get_client_channel_list(server, entry);
610 SILC_PUT32_MSB(entry->mode, mode);
612 if (entry->connection) {
613 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
617 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
619 2, idp->data, idp->len,
623 strlen(entry->userinfo),
629 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
631 2, idp->data, idp->len,
635 strlen(entry->userinfo),
639 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
640 0, packet->data, packet->len, FALSE);
642 silc_buffer_free(packet);
643 silc_buffer_free(idp);
645 silc_buffer_free(channels);
652 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
654 SilcServer server = cmd->server;
655 char *nick = NULL, *server_name = NULL;
657 SilcClientEntry *clients = NULL, entry;
658 SilcClientID **client_id = NULL;
659 uint32 client_id_count = 0, clients_count = 0;
662 /* Protocol dictates that we must always send the received WHOIS request
663 to our router if we are normal server, so let's do it now unless we
664 are standalone. We will not send any replies to the client until we
665 have received reply from the router. */
666 if (server->server_type == SILC_SERVER && !cmd->pending &&
667 !server->standalone) {
671 old_ident = silc_command_get_ident(cmd->payload);
672 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
673 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
675 /* Send WHOIS command to our router */
676 silc_server_packet_send(server, (SilcSocketConnection)
677 server->router->connection,
678 SILC_PACKET_COMMAND, cmd->packet->flags,
679 tmpbuf->data, tmpbuf->len, TRUE);
681 /* Reprocess this packet after received reply from router */
682 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
683 silc_command_get_ident(cmd->payload),
684 silc_server_command_destructor,
685 silc_server_command_whois,
686 silc_server_command_dup(cmd));
689 silc_command_set_ident(cmd->payload, old_ident);
691 silc_buffer_free(tmpbuf);
696 /* We are ready to process the command request. Let's search for the
697 requested client and send reply to the requesting client. */
699 /* Parse the whois request */
700 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
701 &nick, &server_name, &count,
705 /* Get all clients matching that ID or nickname from local list */
706 if (client_id_count) {
707 /* Check all Client ID's received in the command packet */
708 for (i = 0; i < client_id_count; i++) {
709 entry = silc_idlist_find_client_by_id(server->local_list,
712 clients = silc_realloc(clients, sizeof(*clients) *
713 (clients_count + 1));
714 clients[clients_count++] = entry;
718 if (!silc_idlist_get_clients_by_hash(server->local_list,
719 nick, server->md5hash,
720 &clients, &clients_count))
721 silc_idlist_get_clients_by_nickname(server->local_list,
723 &clients, &clients_count);
726 /* Check global list as well */
727 if (client_id_count) {
728 /* Check all Client ID's received in the command packet */
729 for (i = 0; i < client_id_count; i++) {
730 entry = silc_idlist_find_client_by_id(server->global_list,
733 clients = silc_realloc(clients, sizeof(*clients) *
734 (clients_count + 1));
735 clients[clients_count++] = entry;
739 if (!silc_idlist_get_clients_by_hash(server->global_list,
740 nick, server->md5hash,
741 &clients, &clients_count))
742 silc_idlist_get_clients_by_nickname(server->global_list,
744 &clients, &clients_count);
748 /* Such client(s) really does not exist in the SILC network. */
749 if (!client_id_count) {
750 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
751 SILC_STATUS_ERR_NO_SUCH_NICK,
752 3, nick, strlen(nick));
754 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
755 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
756 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
757 2, idp->data, idp->len);
758 silc_buffer_free(idp);
763 /* Router always finds the client entry if it exists in the SILC network.
764 However, it might be incomplete entry and does not include all the
765 mandatory fields that WHOIS command reply requires. Check for these and
766 make query from the server who owns the client if some fields are
768 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
773 /* Send the command reply to the client */
774 silc_server_command_whois_send_reply(cmd, clients, clients_count,
778 if (client_id_count) {
779 for (i = 0; i < client_id_count; i++)
780 silc_free(client_id[i]);
781 silc_free(client_id);
788 silc_free(server_name);
794 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
796 SilcServer server = cmd->server;
797 char *nick = NULL, *server_name = NULL;
799 SilcClientEntry *clients = NULL, entry;
800 SilcClientID **client_id = NULL;
801 uint32 client_id_count = 0, clients_count = 0;
804 /* Parse the whois request */
805 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
806 &nick, &server_name, &count,
810 /* Process the command request. Let's search for the requested client and
811 send reply to the requesting server. */
813 if (client_id_count) {
814 /* Check all Client ID's received in the command packet */
815 for (i = 0; i < client_id_count; i++) {
816 entry = silc_idlist_find_client_by_id(server->local_list,
819 clients = silc_realloc(clients, sizeof(*clients) *
820 (clients_count + 1));
821 clients[clients_count++] = entry;
825 if (!silc_idlist_get_clients_by_hash(server->local_list,
826 nick, server->md5hash,
827 &clients, &clients_count))
828 silc_idlist_get_clients_by_nickname(server->local_list,
830 &clients, &clients_count);
833 /* If we are router we will check our global list as well. */
834 if (server->server_type == SILC_ROUTER) {
835 if (client_id_count) {
836 /* Check all Client ID's received in the command packet */
837 for (i = 0; i < client_id_count; i++) {
838 entry = silc_idlist_find_client_by_id(server->global_list,
841 clients = silc_realloc(clients, sizeof(*clients) *
842 (clients_count + 1));
843 clients[clients_count++] = entry;
847 if (!silc_idlist_get_clients_by_hash(server->global_list,
848 nick, server->md5hash,
849 &clients, &clients_count))
850 silc_idlist_get_clients_by_nickname(server->global_list,
852 &clients, &clients_count);
857 /* Such a client really does not exist in the SILC network. */
858 if (!client_id_count) {
859 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
860 SILC_STATUS_ERR_NO_SUCH_NICK,
861 3, nick, strlen(nick));
863 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
864 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
865 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
866 2, idp->data, idp->len);
867 silc_buffer_free(idp);
872 /* Router always finds the client entry if it exists in the SILC network.
873 However, it might be incomplete entry and does not include all the
874 mandatory fields that WHOIS command reply requires. Check for these and
875 make query from the server who owns the client if some fields are
877 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
882 /* Send the command reply to the client */
883 silc_server_command_whois_send_reply(cmd, clients, clients_count,
887 if (client_id_count) {
888 for (i = 0; i < client_id_count; i++)
889 silc_free(client_id[i]);
890 silc_free(client_id);
897 silc_free(server_name);
902 /* Server side of command WHOIS. Processes user's query and sends found
903 results as command replies back to the client. */
905 SILC_SERVER_CMD_FUNC(whois)
907 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
910 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
912 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
913 ret = silc_server_command_whois_from_client(cmd);
914 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
915 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
916 ret = silc_server_command_whois_from_server(cmd);
919 silc_server_command_free(cmd);
922 /******************************************************************************
926 ******************************************************************************/
929 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
937 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
939 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
940 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
944 /* Get the nickname@server string and parse it. */
945 if (strchr(tmp, '@')) {
946 len = strcspn(tmp, "@");
947 *nickname = silc_calloc(len + 1, sizeof(char));
948 memcpy(*nickname, tmp, len);
949 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
950 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
952 *nickname = strdup(tmp);
954 /* Get the max count of reply messages allowed */
955 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
965 silc_server_command_whowas_check(SilcServerCommandContext cmd,
966 SilcClientEntry *clients,
967 uint32 clients_count)
969 SilcServer server = cmd->server;
971 SilcClientEntry entry;
973 for (i = 0; i < clients_count; i++) {
976 if (!entry->nickname || !entry->username) {
983 old_ident = silc_command_get_ident(cmd->payload);
984 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
985 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
987 /* Send WHOWAS command */
988 silc_server_packet_send(server, entry->router->connection,
989 SILC_PACKET_COMMAND, cmd->packet->flags,
990 tmpbuf->data, tmpbuf->len, TRUE);
992 /* Reprocess this packet after received reply */
993 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
994 silc_command_get_ident(cmd->payload),
995 silc_server_command_destructor,
996 silc_server_command_whowas,
997 silc_server_command_dup(cmd));
1000 silc_command_set_ident(cmd->payload, old_ident);
1002 silc_buffer_free(tmpbuf);
1011 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1012 SilcClientEntry *clients,
1013 uint32 clients_count)
1015 SilcServer server = cmd->server;
1017 int i, count = 0, len;
1018 SilcBuffer packet, idp;
1019 SilcClientEntry entry = NULL;
1020 SilcCommandStatus status;
1021 uint16 ident = silc_command_get_ident(cmd->payload);
1023 char nh[256], uh[256];
1025 status = SILC_STATUS_OK;
1026 if (clients_count > 1)
1027 status = SILC_STATUS_LIST_START;
1029 for (i = 0; i < clients_count; i++) {
1032 /* We will take only clients that are not valid anymore. They are the
1033 ones that are not registered anymore but still have a ID. They
1034 have disconnected us, and thus valid for WHOWAS. */
1035 if (entry->data.registered == TRUE)
1037 if (entry->id == NULL)
1040 if (count && i - 1 == count)
1045 if (clients_count > 2)
1046 status = SILC_STATUS_LIST_ITEM;
1048 if (clients_count > 1 && i == clients_count - 1)
1049 status = SILC_STATUS_LIST_END;
1051 /* Sanity check, however these should never fail. However, as
1052 this sanity check has been added here they have failed. */
1053 if (!entry->nickname || !entry->username)
1056 /* Send WHOWAS reply */
1057 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1058 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1060 memset(uh, 0, sizeof(uh));
1061 memset(nh, 0, sizeof(nh));
1063 strncat(nh, entry->nickname, strlen(entry->nickname));
1064 if (!strchr(entry->nickname, '@')) {
1065 strncat(nh, "@", 1);
1066 len = entry->router ? strlen(entry->router->server_name) :
1067 strlen(server->server_name);
1068 strncat(nh, entry->router ? entry->router->server_name :
1069 server->server_name, len);
1072 strncat(uh, entry->username, strlen(entry->username));
1073 if (!strchr(entry->username, '@')) {
1074 strncat(uh, "@", 1);
1075 strcat(uh, "*private*");
1078 if (entry->userinfo)
1080 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1082 2, idp->data, idp->len,
1086 strlen(entry->userinfo));
1089 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1091 2, idp->data, idp->len,
1095 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1096 0, packet->data, packet->len, FALSE);
1098 silc_buffer_free(packet);
1099 silc_buffer_free(idp);
1102 if (found == FALSE && entry)
1103 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1104 SILC_STATUS_ERR_NO_SUCH_NICK,
1106 strlen(entry->nickname));
1110 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1112 SilcServer server = cmd->server;
1113 char *nick = NULL, *server_name = NULL;
1115 SilcClientEntry *clients = NULL;
1116 uint32 clients_count = 0;
1119 /* Protocol dictates that we must always send the received WHOWAS request
1120 to our router if we are normal server, so let's do it now unless we
1121 are standalone. We will not send any replies to the client until we
1122 have received reply from the router. */
1123 if (server->server_type == SILC_SERVER &&
1124 !cmd->pending && !server->standalone) {
1128 old_ident = silc_command_get_ident(cmd->payload);
1129 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1130 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1132 /* Send WHOWAS command to our router */
1133 silc_server_packet_send(server, (SilcSocketConnection)
1134 server->router->connection,
1135 SILC_PACKET_COMMAND, cmd->packet->flags,
1136 tmpbuf->data, tmpbuf->len, TRUE);
1138 /* Reprocess this packet after received reply from router */
1139 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1140 silc_command_get_ident(cmd->payload),
1141 silc_server_command_destructor,
1142 silc_server_command_whowas,
1143 silc_server_command_dup(cmd));
1144 cmd->pending = TRUE;
1146 silc_command_set_ident(cmd->payload, old_ident);
1148 silc_buffer_free(tmpbuf);
1153 /* We are ready to process the command request. Let's search for the
1154 requested client and send reply to the requesting client. */
1156 /* Parse the whowas request */
1157 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1160 /* Get all clients matching that nickname from local list */
1161 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1163 &clients, &clients_count))
1164 silc_idlist_get_clients_by_hash(server->local_list,
1165 nick, server->md5hash,
1166 &clients, &clients_count);
1168 /* Check global list as well */
1169 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1171 &clients, &clients_count))
1172 silc_idlist_get_clients_by_hash(server->global_list,
1173 nick, server->md5hash,
1174 &clients, &clients_count);
1176 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1181 /* Send the command reply to the client */
1182 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1190 silc_free(server_name);
1196 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1198 SilcServer server = cmd->server;
1199 char *nick = NULL, *server_name = NULL;
1201 SilcClientEntry *clients = NULL;
1202 uint32 clients_count = 0;
1205 /* Parse the whowas request */
1206 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1209 /* Process the command request. Let's search for the requested client and
1210 send reply to the requesting server. */
1212 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1214 &clients, &clients_count))
1215 silc_idlist_get_clients_by_hash(server->local_list,
1216 nick, server->md5hash,
1217 &clients, &clients_count);
1219 /* If we are router we will check our global list as well. */
1220 if (server->server_type == SILC_ROUTER) {
1221 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1223 &clients, &clients_count))
1224 silc_idlist_get_clients_by_hash(server->global_list,
1225 nick, server->md5hash,
1226 &clients, &clients_count);
1230 /* Such a client really does not exist in the SILC network. */
1231 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1232 SILC_STATUS_ERR_NO_SUCH_NICK,
1233 3, nick, strlen(nick));
1237 /* Send the command reply to the client */
1238 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1246 silc_free(server_name);
1251 /* Server side of command WHOWAS. */
1253 SILC_SERVER_CMD_FUNC(whowas)
1255 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1258 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1260 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1261 ret = silc_server_command_whowas_from_client(cmd);
1262 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1263 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1264 ret = silc_server_command_whowas_from_server(cmd);
1267 silc_server_command_free(cmd);
1270 /******************************************************************************
1274 ******************************************************************************/
1276 /* Checks that all mandatory fields are present. If not then send WHOIS
1277 request to the server who owns the client. We use WHOIS because we want
1278 to get as much information as possible at once. */
1281 silc_server_command_identify_check(SilcServerCommandContext cmd,
1282 SilcClientEntry *clients,
1283 uint32 clients_count)
1285 SilcServer server = cmd->server;
1287 SilcClientEntry entry;
1289 for (i = 0; i < clients_count; i++) {
1292 if (!entry || entry->data.registered == FALSE)
1295 if (!entry->nickname) {
1302 old_ident = silc_command_get_ident(cmd->payload);
1303 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1304 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1305 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1307 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1308 now anyway so make it a good one. */
1309 silc_server_packet_send(server, entry->router->connection,
1310 SILC_PACKET_COMMAND, cmd->packet->flags,
1311 tmpbuf->data, tmpbuf->len, TRUE);
1313 /* Reprocess this packet after received reply */
1314 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1315 silc_command_get_ident(cmd->payload),
1316 silc_server_command_destructor,
1317 silc_server_command_identify,
1318 silc_server_command_dup(cmd));
1320 cmd->pending = TRUE;
1322 /* Put old data back to the Command Payload we just changed */
1323 silc_command_set_ident(cmd->payload, old_ident);
1324 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1326 silc_buffer_free(tmpbuf);
1335 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1336 SilcClientEntry *clients,
1337 uint32 clients_count,
1340 SilcServer server = cmd->server;
1343 SilcBuffer packet, idp;
1344 SilcClientEntry entry;
1345 SilcCommandStatus status;
1346 uint16 ident = silc_command_get_ident(cmd->payload);
1347 char nh[256], uh[256];
1348 SilcSocketConnection hsock;
1351 for (i = 0; i < clients_count; i++)
1352 if (clients[i]->data.registered)
1355 status = SILC_STATUS_OK;
1357 status = SILC_STATUS_LIST_START;
1359 for (i = 0, k = 0; i < clients_count; i++) {
1362 if (entry->data.registered == FALSE) {
1363 if (clients_count == 1) {
1364 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1365 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1366 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1367 2, idp->data, idp->len);
1368 silc_buffer_free(idp);
1374 status = SILC_STATUS_LIST_ITEM;
1376 if (clients_count > 1 && k == clients_count - 1)
1377 status = SILC_STATUS_LIST_END;
1379 if (count && k - 1 == count)
1380 status = SILC_STATUS_LIST_END;
1382 if (count && k - 1 > count)
1385 /* Send IDENTIFY reply */
1386 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1387 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1389 memset(uh, 0, sizeof(uh));
1390 memset(nh, 0, sizeof(nh));
1392 strncat(nh, entry->nickname, strlen(entry->nickname));
1393 if (!strchr(entry->nickname, '@')) {
1394 strncat(nh, "@", 1);
1395 len = entry->router ? strlen(entry->router->server_name) :
1396 strlen(server->server_name);
1397 strncat(nh, entry->router ? entry->router->server_name :
1398 server->server_name, len);
1401 if (!entry->username) {
1402 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1404 2, idp->data, idp->len,
1407 strncat(uh, entry->username, strlen(entry->username));
1408 if (!strchr(entry->username, '@')) {
1409 strncat(uh, "@", 1);
1410 hsock = (SilcSocketConnection)entry->connection;
1411 len = strlen(hsock->hostname);
1412 strncat(uh, hsock->hostname, len);
1415 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1417 2, idp->data, idp->len,
1422 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1423 0, packet->data, packet->len, FALSE);
1425 silc_buffer_free(packet);
1426 silc_buffer_free(idp);
1433 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1435 SilcServer server = cmd->server;
1436 char *nick = NULL, *server_name = NULL;
1438 SilcClientEntry *clients = NULL, entry;
1439 SilcClientID **client_id = NULL;
1440 uint32 client_id_count = 0, clients_count = 0;
1443 /* Protocol dictates that we must always send the received IDENTIFY request
1444 to our router if we are normal server, so let's do it now unless we
1445 are standalone. We will not send any replies to the client until we
1446 have received reply from the router. */
1447 if (server->server_type == SILC_SERVER &&
1448 !cmd->pending && !server->standalone) {
1452 old_ident = silc_command_get_ident(cmd->payload);
1453 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1454 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1456 /* Send IDENTIFY command to our router */
1457 silc_server_packet_send(server, (SilcSocketConnection)
1458 server->router->connection,
1459 SILC_PACKET_COMMAND, cmd->packet->flags,
1460 tmpbuf->data, tmpbuf->len, TRUE);
1462 /* Reprocess this packet after received reply from router */
1463 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1464 silc_command_get_ident(cmd->payload),
1465 silc_server_command_destructor,
1466 silc_server_command_identify,
1467 silc_server_command_dup(cmd));
1468 cmd->pending = TRUE;
1470 silc_command_set_ident(cmd->payload, old_ident);
1472 silc_buffer_free(tmpbuf);
1477 /* We are ready to process the command request. Let's search for the
1478 requested client and send reply to the requesting client. */
1480 /* Parse the IDENTIFY request */
1481 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1482 &nick, &server_name, &count,
1483 SILC_COMMAND_IDENTIFY))
1486 /* Get all clients matching that ID or nickname from local list */
1487 if (client_id_count) {
1488 /* Check all Client ID's received in the command packet */
1489 for (i = 0; i < client_id_count; i++) {
1490 entry = silc_idlist_find_client_by_id(server->local_list,
1491 client_id[i], NULL);
1493 clients = silc_realloc(clients, sizeof(*clients) *
1494 (clients_count + 1));
1495 clients[clients_count++] = entry;
1499 if (!silc_idlist_get_clients_by_hash(server->local_list,
1500 nick, server->md5hash,
1501 &clients, &clients_count))
1502 silc_idlist_get_clients_by_nickname(server->local_list,
1504 &clients, &clients_count);
1507 /* Check global list as well */
1508 if (client_id_count) {
1509 /* Check all Client ID's received in the command packet */
1510 for (i = 0; i < client_id_count; i++) {
1511 entry = silc_idlist_find_client_by_id(server->global_list,
1512 client_id[i], NULL);
1514 clients = silc_realloc(clients, sizeof(*clients) *
1515 (clients_count + 1));
1516 clients[clients_count++] = entry;
1520 if (!silc_idlist_get_clients_by_hash(server->global_list,
1521 nick, server->md5hash,
1522 &clients, &clients_count))
1523 silc_idlist_get_clients_by_nickname(server->global_list,
1525 &clients, &clients_count);
1529 /* Such a client really does not exist in the SILC network. */
1530 if (!client_id_count) {
1531 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1532 SILC_STATUS_ERR_NO_SUCH_NICK,
1533 3, nick, strlen(nick));
1535 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1536 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1537 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1538 2, idp->data, idp->len);
1539 silc_buffer_free(idp);
1544 /* Check that all mandatory fields are present and request those data
1545 from the server who owns the client if necessary. */
1546 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1551 /* Send the command reply to the client */
1552 silc_server_command_identify_send_reply(cmd, clients, clients_count,
1556 if (client_id_count) {
1557 for (i = 0; i < client_id_count; i++)
1558 silc_free(client_id[i]);
1559 silc_free(client_id);
1566 silc_free(server_name);
1572 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1574 SilcServer server = cmd->server;
1575 char *nick = NULL, *server_name = NULL;
1577 SilcClientEntry *clients = NULL, entry;
1578 SilcClientID **client_id = NULL;
1579 uint32 client_id_count = 0, clients_count = 0;
1582 /* Parse the IDENTIFY request */
1583 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1584 &nick, &server_name, &count,
1585 SILC_COMMAND_IDENTIFY))
1588 /* Process the command request. Let's search for the requested client and
1589 send reply to the requesting server. */
1591 if (client_id_count) {
1592 /* Check all Client ID's received in the command packet */
1593 for (i = 0; i < client_id_count; i++) {
1594 entry = silc_idlist_find_client_by_id(server->local_list,
1595 client_id[i], NULL);
1597 clients = silc_realloc(clients, sizeof(*clients) *
1598 (clients_count + 1));
1599 clients[clients_count++] = entry;
1603 if (!silc_idlist_get_clients_by_hash(server->local_list,
1604 nick, server->md5hash,
1605 &clients, &clients_count))
1606 silc_idlist_get_clients_by_nickname(server->local_list,
1608 &clients, &clients_count);
1611 /* If we are router we will check our global list as well. */
1612 if (server->server_type == SILC_ROUTER) {
1613 if (client_id_count) {
1614 /* Check all Client ID's received in the command packet */
1615 for (i = 0; i < client_id_count; i++) {
1616 entry = silc_idlist_find_client_by_id(server->global_list,
1617 client_id[i], NULL);
1619 clients = silc_realloc(clients, sizeof(*clients) *
1620 (clients_count + 1));
1621 clients[clients_count++] = entry;
1625 if (!silc_idlist_get_clients_by_hash(server->global_list,
1626 nick, server->md5hash,
1627 &clients, &clients_count))
1628 silc_idlist_get_clients_by_nickname(server->global_list,
1630 &clients, &clients_count);
1635 /* Such a client really does not exist in the SILC network. */
1636 if (!client_id_count) {
1637 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1638 SILC_STATUS_ERR_NO_SUCH_NICK,
1639 3, nick, strlen(nick));
1641 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1642 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1643 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1644 2, idp->data, idp->len);
1645 silc_buffer_free(idp);
1650 /* Check that all mandatory fields are present and request those data
1651 from the server who owns the client if necessary. */
1652 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1657 /* Send the command reply */
1658 silc_server_command_identify_send_reply(cmd, clients, clients_count, count);
1661 if (client_id_count) {
1662 for (i = 0; i < client_id_count; i++)
1663 silc_free(client_id[i]);
1664 silc_free(client_id);
1671 silc_free(server_name);
1676 SILC_SERVER_CMD_FUNC(identify)
1678 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1681 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1683 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1684 ret = silc_server_command_identify_from_client(cmd);
1685 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1686 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1687 ret = silc_server_command_identify_from_server(cmd);
1690 silc_server_command_free(cmd);
1693 /* Checks string for bad characters and returns TRUE if they are found. */
1695 static int silc_server_command_bad_chars(char *nick)
1697 if (strchr(nick, '\\')) return TRUE;
1698 if (strchr(nick, '\"')) return TRUE;
1699 if (strchr(nick, '´')) return TRUE;
1700 if (strchr(nick, '`')) return TRUE;
1701 if (strchr(nick, '\'')) return TRUE;
1702 if (strchr(nick, '*')) return TRUE;
1703 if (strchr(nick, '/')) return TRUE;
1704 if (strchr(nick, '@')) return TRUE;
1709 /* Server side of command NICK. Sets nickname for user. Setting
1710 nickname causes generation of a new client ID for the client. The
1711 new client ID is sent to the client after changing the nickname. */
1713 SILC_SERVER_CMD_FUNC(nick)
1715 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1716 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1717 SilcServer server = cmd->server;
1718 SilcBuffer packet, nidp, oidp;
1719 SilcClientID *new_id;
1721 uint16 ident = silc_command_get_ident(cmd->payload);
1723 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1726 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1728 /* Check nickname */
1729 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1730 if (silc_server_command_bad_chars(nick) == TRUE) {
1731 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1732 SILC_STATUS_ERR_BAD_NICKNAME);
1736 if (strlen(nick) > 128)
1739 /* Create new Client ID */
1740 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1741 cmd->server->md5hash, nick,
1744 /* Send notify about nickname change to our router. We send the new
1745 ID and ask to replace it with the old one. If we are router the
1746 packet is broadcasted. Send NICK_CHANGE notify. */
1747 if (!server->standalone)
1748 silc_server_send_notify_nick_change(server, server->router->connection,
1749 server->server_type == SILC_SERVER ?
1750 FALSE : TRUE, client->id,
1751 new_id, SILC_ID_CLIENT_LEN);
1753 /* Remove old cache entry */
1754 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1757 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1761 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1762 silc_free(client->id);
1765 /* Save the nickname as this client is our local client */
1766 if (client->nickname)
1767 silc_free(client->nickname);
1769 client->nickname = strdup(nick);
1770 client->id = new_id;
1772 /* Update client cache */
1773 silc_idcache_add(server->local_list->clients, client->nickname,
1774 strlen(client->nickname), SILC_ID_CLIENT, client->id,
1775 (void *)client, TRUE, FALSE);
1777 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1779 /* Send NICK_CHANGE notify to the client's channels */
1780 silc_server_send_notify_on_channels(server, NULL, client,
1781 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1782 oidp->data, oidp->len,
1783 nidp->data, nidp->len);
1785 /* Send the new Client ID as reply command back to client */
1786 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1787 SILC_STATUS_OK, ident, 1,
1788 2, nidp->data, nidp->len);
1789 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1790 0, packet->data, packet->len, FALSE);
1792 silc_buffer_free(packet);
1793 silc_buffer_free(nidp);
1794 silc_buffer_free(oidp);
1797 silc_server_command_free(cmd);
1800 /* Sends the LIST command reply */
1803 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1804 SilcChannelEntry *lch,
1806 SilcChannelEntry *gch,
1810 SilcBuffer packet, idp;
1811 SilcChannelEntry entry;
1812 SilcCommandStatus status;
1813 uint16 ident = silc_command_get_ident(cmd->payload);
1815 unsigned char usercount[4];
1818 for (i = 0; i < lch_count; i++)
1819 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1821 for (i = 0; i < gch_count; i++)
1822 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1825 status = SILC_STATUS_OK;
1826 if ((lch_count + gch_count) > 1)
1827 status = SILC_STATUS_LIST_START;
1830 for (i = 0; i < lch_count; i++) {
1837 status = SILC_STATUS_LIST_ITEM;
1839 if (i == lch_count - 1 && gch_count)
1841 if (lch_count > 1 && i == lch_count - 1)
1842 status = SILC_STATUS_LIST_END;
1844 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1846 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1847 topic = "*private*";
1848 memset(usercount, 0, sizeof(usercount));
1850 topic = entry->topic;
1851 users = silc_list_count(entry->user_list);
1852 SILC_PUT32_MSB(users, usercount);
1855 /* Send the reply */
1858 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1860 2, idp->data, idp->len,
1861 3, entry->channel_name,
1862 strlen(entry->channel_name),
1863 4, topic, strlen(topic),
1867 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1869 2, idp->data, idp->len,
1870 3, entry->channel_name,
1871 strlen(entry->channel_name),
1873 silc_server_packet_send(cmd->server, cmd->sock,
1874 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1875 packet->len, FALSE);
1876 silc_buffer_free(packet);
1877 silc_buffer_free(idp);
1880 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1883 for (i = 0; i < gch_count; i++) {
1890 status = SILC_STATUS_LIST_ITEM;
1892 if (gch_count > 1 && i == lch_count - 1)
1893 status = SILC_STATUS_LIST_END;
1895 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1897 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1898 topic = "*private*";
1899 memset(usercount, 0, sizeof(usercount));
1901 topic = entry->topic;
1902 users = silc_list_count(entry->user_list);
1903 SILC_PUT32_MSB(users, usercount);
1906 /* Send the reply */
1909 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1911 2, idp->data, idp->len,
1912 3, entry->channel_name,
1913 strlen(entry->channel_name),
1914 4, topic, strlen(topic),
1918 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1920 2, idp->data, idp->len,
1921 3, entry->channel_name,
1922 strlen(entry->channel_name),
1924 silc_server_packet_send(cmd->server, cmd->sock,
1925 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1926 packet->len, FALSE);
1927 silc_buffer_free(packet);
1928 silc_buffer_free(idp);
1932 /* Server side of LIST command. This lists the channel of the requested
1933 server. Secret channels are not listed. */
1935 SILC_SERVER_CMD_FUNC(list)
1937 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1938 SilcServer server = cmd->server;
1939 SilcChannelID *channel_id = NULL;
1942 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1943 uint32 lch_count = 0, gch_count = 0;
1945 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1947 /* Get Channel ID */
1948 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1950 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1952 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1953 SILC_STATUS_ERR_NO_CHANNEL_ID);
1958 /* Get the channels from local list */
1959 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1962 /* Get the channels from global list if we are router */
1963 if (server->server_type == SILC_ROUTER)
1964 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1967 /* Send the reply */
1968 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
1969 gchannels, gch_count);
1972 silc_server_command_free(cmd);
1975 /* Server side of TOPIC command. Sets topic for channel and/or returns
1976 current topic to client. */
1978 SILC_SERVER_CMD_FUNC(topic)
1980 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1981 SilcServer server = cmd->server;
1982 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1983 SilcChannelID *channel_id;
1984 SilcChannelEntry channel;
1985 SilcChannelClientEntry chl;
1986 SilcBuffer packet, idp;
1988 uint32 argc, tmp_len;
1989 uint16 ident = silc_command_get_ident(cmd->payload);
1991 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1993 argc = silc_argument_get_arg_num(cmd->args);
1995 /* Get Channel ID */
1996 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1998 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1999 SILC_STATUS_ERR_NO_CHANNEL_ID);
2002 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2005 SILC_STATUS_ERR_NO_CHANNEL_ID);
2009 /* Check whether the channel exists */
2010 channel = silc_idlist_find_channel_by_id(server->local_list,
2013 channel = silc_idlist_find_channel_by_id(server->global_list,
2016 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2017 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2024 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2026 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2027 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2031 if (strlen(tmp) > 256) {
2032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2033 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2037 /* See whether has rights to change topic */
2038 silc_list_start(channel->user_list);
2039 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2040 if (chl->client == client)
2043 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2044 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2045 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2046 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2051 /* Set the topic for channel */
2053 silc_free(channel->topic);
2054 channel->topic = strdup(tmp);
2056 /* Send TOPIC_SET notify type to the network */
2057 if (!server->standalone)
2058 silc_server_send_notify_topic_set(server, server->router->connection,
2059 server->server_type == SILC_ROUTER ?
2060 TRUE : FALSE, channel, client->id,
2061 SILC_ID_CLIENT_LEN, channel->topic);
2063 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2065 /* Send notify about topic change to all clients on the channel */
2066 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2067 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2068 idp->data, idp->len,
2069 channel->topic, strlen(channel->topic));
2070 silc_buffer_free(idp);
2073 /* Send the topic to client as reply packet */
2074 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2076 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2077 SILC_STATUS_OK, ident, 2,
2078 2, idp->data, idp->len,
2080 strlen(channel->topic));
2082 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2083 SILC_STATUS_OK, ident, 1,
2084 2, idp->data, idp->len);
2085 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2086 0, packet->data, packet->len, FALSE);
2088 silc_buffer_free(packet);
2089 silc_buffer_free(idp);
2090 silc_free(channel_id);
2093 silc_server_command_free(cmd);
2096 /* Server side of INVITE command. Invites some client to join some channel.
2097 This command is also used to manage the invite list of the channel. */
2099 SILC_SERVER_CMD_FUNC(invite)
2101 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2102 SilcServer server = cmd->server;
2103 SilcSocketConnection sock = cmd->sock, dest_sock;
2104 SilcChannelClientEntry chl;
2105 SilcClientEntry sender, dest;
2106 SilcClientID *dest_id = NULL;
2107 SilcChannelEntry channel;
2108 SilcChannelID *channel_id = NULL;
2109 SilcIDListData idata;
2110 SilcBuffer idp, idp2, packet;
2111 unsigned char *tmp, *add, *del;
2113 uint16 ident = silc_command_get_ident(cmd->payload);
2115 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2117 /* Get Channel ID */
2118 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2121 SILC_STATUS_ERR_NO_CHANNEL_ID);
2124 channel_id = silc_id_payload_parse_id(tmp, len);
2126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2127 SILC_STATUS_ERR_NO_CHANNEL_ID);
2131 /* Get the channel entry */
2132 channel = silc_idlist_find_channel_by_id(server->local_list,
2135 channel = silc_idlist_find_channel_by_id(server->global_list,
2138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2139 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2144 /* Check whether the sender of this command is on the channel. */
2145 sender = (SilcClientEntry)sock->user_data;
2146 if (!silc_server_client_on_channel(sender, channel)) {
2147 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2148 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2152 /* Check whether the channel is invite-only channel. If yes then the
2153 sender of this command must be at least channel operator. */
2154 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2155 silc_list_start(channel->user_list);
2156 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2157 if (chl->client == sender) {
2158 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2159 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2160 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2167 /* Get destination client ID */
2168 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2172 dest_id = silc_id_payload_parse_id(tmp, len);
2174 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2175 SILC_STATUS_ERR_NO_CLIENT_ID);
2179 /* Get the client entry */
2180 dest = silc_server_get_client_resolve(server, dest_id);
2182 if (server->server_type == SILC_ROUTER) {
2183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2184 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2188 /* The client info is being resolved. Reprocess this packet after
2189 receiving the reply to the query. */
2190 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2192 silc_server_command_destructor,
2193 silc_server_command_invite,
2194 silc_server_command_dup(cmd));
2195 cmd->pending = TRUE;
2196 silc_free(channel_id);
2201 /* Check whether the requested client is already on the channel. */
2202 if (silc_server_client_on_channel(dest, channel)) {
2203 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2204 SILC_STATUS_ERR_USER_ON_CHANNEL);
2208 /* Get route to the client */
2209 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2211 memset(invite, 0, sizeof(invite));
2212 strncat(invite, dest->nickname, strlen(dest->nickname));
2213 strncat(invite, "!", 1);
2214 strncat(invite, dest->username, strlen(dest->username));
2215 if (!strchr(dest->username, '@')) {
2216 strncat(invite, "@", 1);
2217 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2220 len = strlen(invite);
2221 if (!channel->invite_list)
2222 channel->invite_list = silc_calloc(len + 2,
2223 sizeof(*channel->invite_list));
2225 channel->invite_list = silc_realloc(channel->invite_list,
2226 sizeof(*channel->invite_list) *
2228 strlen(channel->invite_list) + 2));
2229 strncat(channel->invite_list, invite, len);
2230 strncat(channel->invite_list, ",", 1);
2232 /* Send notify to the client that is invited to the channel */
2233 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2234 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2235 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2237 SILC_NOTIFY_TYPE_INVITE, 3,
2238 idp->data, idp->len,
2239 channel->channel_name,
2240 strlen(channel->channel_name),
2241 idp2->data, idp2->len);
2242 silc_buffer_free(idp);
2243 silc_buffer_free(idp2);
2246 /* Add the client to the invite list of the channel */
2247 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2249 if (!channel->invite_list)
2250 channel->invite_list = silc_calloc(len + 2,
2251 sizeof(*channel->invite_list));
2253 channel->invite_list = silc_realloc(channel->invite_list,
2254 sizeof(*channel->invite_list) *
2256 strlen(channel->invite_list) + 2));
2257 if (add[len - 1] == ',')
2258 add[len - 1] = '\0';
2260 strncat(channel->invite_list, add, len);
2261 strncat(channel->invite_list, ",", 1);
2264 /* Get the invite to be removed and remove it from the list */
2265 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2266 if (del && channel->invite_list) {
2267 char *start, *end, *n;
2269 if (!strncmp(channel->invite_list, del,
2270 strlen(channel->invite_list) - 1)) {
2271 silc_free(channel->invite_list);
2272 channel->invite_list = NULL;
2274 start = strstr(channel->invite_list, del);
2275 if (start && strlen(start) >= len) {
2277 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2278 strncat(n, channel->invite_list, start - channel->invite_list);
2279 strncat(n, end + 1, ((channel->invite_list +
2280 strlen(channel->invite_list)) - end) - 1);
2281 silc_free(channel->invite_list);
2282 channel->invite_list = n;
2287 /* Send notify to the primary router */
2288 if (!server->standalone)
2289 silc_server_send_notify_invite(server, server->router->connection,
2290 server->server_type == SILC_ROUTER ?
2291 TRUE : FALSE, channel,
2292 sender->id, SILC_ID_CLIENT_LEN,
2295 /* Send command reply */
2296 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2297 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2298 SILC_STATUS_OK, ident, 2,
2300 3, channel->invite_list,
2301 channel->invite_list ?
2302 strlen(channel->invite_list) :
2304 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2305 packet->data, packet->len, FALSE);
2306 silc_buffer_free(packet);
2312 silc_free(channel_id);
2313 silc_server_command_free(cmd);
2318 SilcSocketConnection sock;
2322 /* Quits connection to client. This gets called if client won't
2323 close the connection even when it has issued QUIT command. */
2325 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2327 QuitInternal q = (QuitInternal)context;
2329 /* Free all client specific data, such as client entry and entires
2330 on channels this client may be on. */
2331 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2333 q->sock->user_data = NULL;
2335 /* Close the connection on our side */
2336 silc_server_close_connection(q->server, q->sock);
2338 silc_free(q->signoff);
2342 /* Quits SILC session. This is the normal way to disconnect client. */
2344 SILC_SERVER_CMD_FUNC(quit)
2346 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2347 SilcServer server = cmd->server;
2348 SilcSocketConnection sock = cmd->sock;
2350 unsigned char *tmp = NULL;
2353 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2355 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2358 /* Get destination ID */
2359 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2363 q = silc_calloc(1, sizeof(*q));
2366 q->signoff = tmp ? strdup(tmp) : NULL;
2368 /* We quit the connection with little timeout */
2369 silc_task_register(server->timeout_queue, sock->sock,
2370 silc_server_command_quit_cb, (void *)q,
2371 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2374 silc_server_command_free(cmd);
2377 /* Server side of command KILL. This command is used by router operator
2378 to remove an client from the SILC Network temporarily. */
2380 SILC_SERVER_CMD_FUNC(kill)
2382 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2383 SilcServer server = cmd->server;
2384 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2385 SilcClientEntry remote_client;
2386 SilcClientID *client_id;
2387 unsigned char *tmp, *comment;
2388 uint32 tmp_len, tmp_len2;
2390 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2392 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2395 /* KILL command works only on router */
2396 if (server->server_type != SILC_ROUTER) {
2397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2398 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2402 /* Check whether client has the permissions. */
2403 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2404 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2405 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2409 /* Get the client ID */
2410 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2413 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2416 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2418 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2419 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2423 /* Get the client entry */
2424 remote_client = silc_idlist_find_client_by_id(server->local_list,
2426 if (!remote_client) {
2427 remote_client = silc_idlist_find_client_by_id(server->global_list,
2429 if (!remote_client) {
2430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2431 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2437 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2441 /* Send reply to the sender */
2442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2445 /* Send the KILL notify packets. First send it to the channel, then
2446 to our primary router and then directly to the client who is being
2447 killed right now. */
2449 /* Send KILLED notify to the channels. It is not sent to the client
2450 as it will be sent differently destined directly to the client and not
2452 silc_server_send_notify_on_channels(server, remote_client,
2453 remote_client, SILC_NOTIFY_TYPE_KILLED,
2456 comment, comment ? tmp_len2 : 0);
2458 /* Send KILLED notify to primary route */
2459 if (!server->standalone)
2460 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2461 remote_client->id, SILC_ID_CLIENT_LEN,
2464 /* Send KILLED notify to the client directly */
2465 silc_server_send_notify_killed(server, remote_client->connection ?
2466 remote_client->connection :
2467 remote_client->router->connection, FALSE,
2468 remote_client->id, SILC_ID_CLIENT_LEN,
2471 /* Remove the client from all channels. This generates new keys to the
2472 channels as well. */
2473 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2476 /* Remove the client entry, If it is locally connected then we will also
2477 disconnect the client here */
2478 if (remote_client->data.registered && remote_client->connection) {
2479 /* Remove locally conneted client */
2480 SilcSocketConnection sock = remote_client->connection;
2481 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2482 silc_server_close_connection(server, sock);
2484 /* Remove remote client */
2485 if (!silc_idlist_del_client(server->global_list, remote_client))
2486 silc_idlist_del_client(server->local_list, remote_client);
2490 silc_server_command_free(cmd);
2493 /* Server side of command INFO. This sends information about us to
2494 the client. If client requested specific server we will send the
2495 command to that server. */
2497 SILC_SERVER_CMD_FUNC(info)
2499 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2500 SilcServer server = cmd->server;
2501 SilcBuffer packet, idp;
2504 char *dest_server, *server_info = NULL, *server_name;
2505 uint16 ident = silc_command_get_ident(cmd->payload);
2506 SilcServerEntry entry = NULL;
2507 SilcServerID *server_id = NULL;
2509 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 0, 2);
2511 /* Get server name */
2512 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2515 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2517 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2520 SILC_STATUS_ERR_NO_SERVER_ID);
2526 /* Check whether we have this server cached */
2527 entry = silc_idlist_find_server_by_id(server->local_list,
2530 entry = silc_idlist_find_server_by_id(server->global_list,
2532 if (!entry && server->server_type == SILC_ROUTER) {
2533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2534 SILC_STATUS_ERR_NO_SUCH_SERVER);
2540 if ((!dest_server && !server_id) ||
2541 (dest_server && !cmd->pending &&
2542 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2543 /* Send our reply */
2544 char info_string[256];
2546 memset(info_string, 0, sizeof(info_string));
2547 snprintf(info_string, sizeof(info_string),
2548 "location: %s server: %s admin: %s <%s>",
2549 server->config->admin_info->location,
2550 server->config->admin_info->server_type,
2551 server->config->admin_info->admin_name,
2552 server->config->admin_info->admin_email);
2554 server_info = info_string;
2555 entry = server->id_entry;
2557 /* Check whether we have this server cached */
2558 if (!entry && dest_server) {
2559 entry = silc_idlist_find_server_by_name(server->global_list,
2562 entry = silc_idlist_find_server_by_name(server->local_list,
2567 if (!cmd->pending &&
2568 server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2569 /* Send to the server */
2573 old_ident = silc_command_get_ident(cmd->payload);
2574 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2575 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2577 silc_server_packet_send(server, entry->connection,
2578 SILC_PACKET_COMMAND, cmd->packet->flags,
2579 tmpbuf->data, tmpbuf->len, TRUE);
2581 /* Reprocess this packet after received reply from router */
2582 silc_server_command_pending(server, SILC_COMMAND_INFO,
2583 silc_command_get_ident(cmd->payload),
2584 silc_server_command_destructor,
2585 silc_server_command_info,
2586 silc_server_command_dup(cmd));
2587 cmd->pending = TRUE;
2588 silc_command_set_ident(cmd->payload, old_ident);
2589 silc_buffer_free(tmpbuf);
2593 if (!entry && !cmd->pending && !server->standalone) {
2594 /* Send to the primary router */
2598 old_ident = silc_command_get_ident(cmd->payload);
2599 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2600 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2602 silc_server_packet_send(server, server->router->connection,
2603 SILC_PACKET_COMMAND, cmd->packet->flags,
2604 tmpbuf->data, tmpbuf->len, TRUE);
2606 /* Reprocess this packet after received reply from router */
2607 silc_server_command_pending(server, SILC_COMMAND_INFO,
2608 silc_command_get_ident(cmd->payload),
2609 silc_server_command_destructor,
2610 silc_server_command_info,
2611 silc_server_command_dup(cmd));
2612 cmd->pending = TRUE;
2613 silc_command_set_ident(cmd->payload, old_ident);
2614 silc_buffer_free(tmpbuf);
2620 silc_free(server_id);
2623 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2624 SILC_STATUS_ERR_NO_SUCH_SERVER);
2628 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2630 server_info = entry->server_info;
2631 server_name = entry->server_name;
2633 /* Send the reply */
2634 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2635 SILC_STATUS_OK, ident, 3,
2636 2, idp->data, idp->len,
2638 strlen(server_name),
2640 strlen(server_info));
2641 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2642 packet->data, packet->len, FALSE);
2644 silc_buffer_free(packet);
2645 silc_buffer_free(idp);
2648 silc_server_command_free(cmd);
2651 /* Server side of command PING. This just replies to the ping. */
2653 SILC_SERVER_CMD_FUNC(ping)
2655 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2656 SilcServer server = cmd->server;
2661 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2664 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2666 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2667 SILC_STATUS_ERR_NO_SERVER_ID);
2670 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2674 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2675 /* Send our reply */
2676 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2680 SILC_STATUS_ERR_NO_SUCH_SERVER);
2687 silc_server_command_free(cmd);
2690 /* Internal routine to join channel. The channel sent to this function
2691 has been either created or resolved from ID lists. This joins the sent
2692 client to the channel. */
2694 static void silc_server_command_join_channel(SilcServer server,
2695 SilcServerCommandContext cmd,
2696 SilcChannelEntry channel,
2697 SilcClientID *client_id,
2701 SilcSocketConnection sock = cmd->sock;
2703 uint32 tmp_len, user_count;
2704 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2705 SilcClientEntry client;
2706 SilcChannelClientEntry chl;
2707 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2708 uint16 ident = silc_command_get_ident(cmd->payload);
2711 SILC_LOG_DEBUG(("Start"));
2716 /* Get the client entry */
2717 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2718 client = (SilcClientEntry)sock->user_data;
2720 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2727 * Check channel modes
2730 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2731 strncat(check, client->nickname, strlen(client->nickname));
2732 if (!strchr(client->nickname, '@')) {
2733 strncat(check, "@", 1);
2734 strncat(check, server->server_name, strlen(server->server_name));
2736 strncat(check, "!", 1);
2737 strncat(check, client->username, strlen(client->username));
2738 if (!strchr(client->username, '@')) {
2739 strncat(check, "@", 1);
2740 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2744 /* Check invite list if channel is invite-only channel */
2745 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
2746 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2747 if (!channel->invite_list) {
2748 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2749 SILC_STATUS_ERR_NOT_INVITED);
2753 if (!silc_string_match(channel->invite_list, check)) {
2754 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2755 SILC_STATUS_ERR_NOT_INVITED);
2760 /* Check ban list if it exists. If the client's nickname, server,
2761 username and/or hostname is in the ban list the access to the
2762 channel is denied. */
2763 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2764 if (silc_string_match(channel->ban_list, check)) {
2765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2766 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2771 /* Get passphrase */
2772 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2774 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2775 memcpy(passphrase, tmp, tmp_len);
2778 /* Check the channel passphrase if set. */
2779 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2780 if (!passphrase || memcmp(channel->passphrase, passphrase,
2781 strlen(channel->passphrase))) {
2782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2783 SILC_STATUS_ERR_BAD_PASSWORD);
2788 /* Check user count limit if set. */
2789 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2790 if (silc_list_count(channel->user_list) + 1 >
2791 channel->user_limit) {
2792 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2793 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2799 * Client is allowed to join to the channel. Make it happen.
2802 /* Check whether the client already is on the channel */
2803 if (silc_server_client_on_channel(client, channel)) {
2804 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2805 SILC_STATUS_ERR_USER_ON_CHANNEL);
2809 /* Generate new channel key as protocol dictates */
2810 if ((!created && silc_list_count(channel->user_list) > 0) ||
2811 !channel->channel_key)
2812 silc_server_create_channel_key(server, channel, 0);
2814 /* Send the channel key. This is broadcasted to the channel but is not
2815 sent to the client who is joining to the channel. */
2816 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2817 silc_server_send_channel_key(server, NULL, channel,
2818 server->server_type == SILC_ROUTER ?
2819 FALSE : !server->standalone);
2821 /* Join the client to the channel by adding it to channel's user list.
2822 Add also the channel to client entry's channels list for fast cross-
2824 chl = silc_calloc(1, sizeof(*chl));
2826 chl->client = client;
2827 chl->channel = channel;
2828 silc_list_add(channel->user_list, chl);
2829 silc_list_add(client->channels, chl);
2831 /* Get users on the channel */
2832 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2835 /* Encode Client ID Payload of the original client who wants to join */
2836 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2838 /* Encode command reply packet */
2839 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2840 SILC_PUT32_MSB(channel->mode, mode);
2841 SILC_PUT32_MSB(created, tmp2);
2842 SILC_PUT32_MSB(user_count, tmp3);
2844 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2845 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2846 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2847 strlen(channel->channel_key->
2849 channel->channel_key->cipher->name,
2850 channel->key_len / 8, channel->key);
2855 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2856 SILC_STATUS_OK, ident, 13,
2857 2, channel->channel_name,
2858 strlen(channel->channel_name),
2859 3, chidp->data, chidp->len,
2860 4, clidp->data, clidp->len,
2863 7, keyp ? keyp->data : NULL,
2864 keyp ? keyp->len : 0,
2865 8, channel->ban_list,
2867 strlen(channel->ban_list) : 0,
2868 9, channel->invite_list,
2869 channel->invite_list ?
2870 strlen(channel->invite_list) : 0,
2873 strlen(channel->topic) : 0,
2874 11, channel->hmac->hmac->name,
2875 strlen(channel->hmac->hmac->name),
2877 13, user_list->data, user_list->len,
2878 14, mode_list->data,
2881 /* Send command reply */
2882 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2883 reply->data, reply->len, FALSE);
2885 if (!cmd->pending) {
2886 /* Send JOIN notify to locally connected clients on the channel */
2887 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2888 SILC_NOTIFY_TYPE_JOIN, 2,
2889 clidp->data, clidp->len,
2890 chidp->data, chidp->len);
2892 /* Send JOIN notify packet to our primary router */
2893 if (!server->standalone)
2894 silc_server_send_notify_join(server, server->router->connection,
2895 server->server_type == SILC_ROUTER ?
2896 TRUE : FALSE, channel, client->id,
2897 SILC_ID_CLIENT_LEN);
2900 silc_buffer_free(reply);
2901 silc_buffer_free(clidp);
2902 silc_buffer_free(chidp);
2903 silc_buffer_free(keyp);
2904 silc_buffer_free(user_list);
2905 silc_buffer_free(mode_list);
2909 silc_free(passphrase);
2912 /* Server side of command JOIN. Joins client into requested channel. If
2913 the channel does not exist it will be created. */
2915 SILC_SERVER_CMD_FUNC(join)
2917 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2918 SilcServer server = cmd->server;
2920 char *tmp, *channel_name = NULL, *cipher, *hmac;
2921 SilcChannelEntry channel;
2923 int created = FALSE;
2924 SilcClientID *client_id;
2926 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2928 /* Get channel name */
2929 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2931 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2932 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2937 if (strlen(channel_name) > 256)
2938 channel_name[255] = '\0';
2940 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2942 SILC_STATUS_ERR_BAD_CHANNEL);
2943 silc_free(channel_name);
2947 /* Get Client ID of the client who is joining to the channel */
2948 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2951 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2954 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2956 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2957 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2961 /* Get cipher and hmac name */
2962 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2963 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2965 /* See if the channel exists */
2966 channel = silc_idlist_find_channel_by_name(server->local_list,
2967 channel_name, NULL);
2969 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2970 /* If this is coming from client the Client ID in the command packet must
2971 be same as the client's ID. */
2972 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2973 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2974 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2975 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2976 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2981 if (!channel || !channel->id) {
2982 /* Channel not found */
2984 /* If we are standalone server we don't have a router, we just create
2985 the channel by ourselves. */
2986 if (server->standalone) {
2987 channel = silc_server_create_new_channel(server, server->id, cipher,
2988 hmac, channel_name, TRUE);
2990 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2991 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2995 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3000 /* The channel does not exist on our server. If we are normal server
3001 we will send JOIN command to our router which will handle the
3002 joining procedure (either creates the channel if it doesn't exist
3003 or joins the client to it). */
3004 if (server->server_type == SILC_SERVER) {
3008 old_ident = silc_command_get_ident(cmd->payload);
3009 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3010 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3012 /* Send JOIN command to our router */
3013 silc_server_packet_send(server, (SilcSocketConnection)
3014 server->router->connection,
3015 SILC_PACKET_COMMAND, cmd->packet->flags,
3016 tmpbuf->data, tmpbuf->len, TRUE);
3018 /* Reprocess this packet after received reply from router */
3019 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3020 silc_command_get_ident(cmd->payload),
3021 silc_server_command_destructor,
3022 silc_server_command_join,
3023 silc_server_command_dup(cmd));
3024 cmd->pending = TRUE;
3028 /* We are router and the channel does not seem exist so we will check
3029 our global list as well for the channel. */
3030 channel = silc_idlist_find_channel_by_name(server->global_list,
3031 channel_name, NULL);
3033 /* Channel really does not exist, create it */
3034 channel = silc_server_create_new_channel(server, server->id, cipher,
3035 hmac, channel_name, TRUE);
3037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3038 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3042 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3049 /* Channel not found */
3051 /* If the command came from router and/or we are normal server then
3052 something went wrong with the joining as the channel was not found.
3053 We can't do anything else but ignore this. */
3054 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3055 server->server_type == SILC_SERVER)
3058 /* We are router and the channel does not seem exist so we will check
3059 our global list as well for the channel. */
3060 channel = silc_idlist_find_channel_by_name(server->global_list,
3061 channel_name, NULL);
3063 /* Channel really does not exist, create it */
3064 channel = silc_server_create_new_channel(server, server->id, cipher,
3065 hmac, channel_name, TRUE);
3067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3068 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3072 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3078 /* If the channel does not have global users and is also empty it means the
3079 channel was created globally (by our router) and the client will be the
3080 channel founder and operator. */
3081 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3082 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3083 created = TRUE; /* Created globally by our router */
3086 /* Join to the channel */
3087 silc_server_command_join_channel(server, cmd, channel, client_id,
3090 silc_free(client_id);
3093 silc_server_command_free(cmd);
3096 /* Server side of command MOTD. Sends server's current "message of the
3097 day" to the client. */
3099 SILC_SERVER_CMD_FUNC(motd)
3101 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3102 SilcServer server = cmd->server;
3103 SilcBuffer packet, idp;
3104 char *motd, *dest_server;
3106 uint16 ident = silc_command_get_ident(cmd->payload);
3108 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3110 /* Get server name */
3111 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3113 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3114 SILC_STATUS_ERR_NO_SUCH_SERVER);
3118 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3121 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3123 if (server->config && server->config->motd &&
3124 server->config->motd->motd_file) {
3126 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3131 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3132 SILC_STATUS_OK, ident, 2,
3138 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3139 SILC_STATUS_OK, ident, 1,
3143 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3144 packet->data, packet->len, FALSE);
3145 silc_buffer_free(packet);
3146 silc_buffer_free(idp);
3148 SilcServerEntry entry;
3150 /* Check whether we have this server cached */
3151 entry = silc_idlist_find_server_by_name(server->global_list,
3154 entry = silc_idlist_find_server_by_name(server->local_list,
3158 if (server->server_type == SILC_ROUTER && !cmd->pending &&
3159 entry && !entry->motd) {
3160 /* Send to the server */
3164 old_ident = silc_command_get_ident(cmd->payload);
3165 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3166 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3168 silc_server_packet_send(server, entry->connection,
3169 SILC_PACKET_COMMAND, cmd->packet->flags,
3170 tmpbuf->data, tmpbuf->len, TRUE);
3172 /* Reprocess this packet after received reply from router */
3173 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3174 silc_command_get_ident(cmd->payload),
3175 silc_server_command_destructor,
3176 silc_server_command_motd,
3177 silc_server_command_dup(cmd));
3178 cmd->pending = TRUE;
3179 silc_command_set_ident(cmd->payload, old_ident);
3180 silc_buffer_free(tmpbuf);
3184 if (!entry && !cmd->pending && !server->standalone) {
3185 /* Send to the primary router */
3189 old_ident = silc_command_get_ident(cmd->payload);
3190 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3191 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3193 silc_server_packet_send(server, server->router->connection,
3194 SILC_PACKET_COMMAND, cmd->packet->flags,
3195 tmpbuf->data, tmpbuf->len, TRUE);
3197 /* Reprocess this packet after received reply from router */
3198 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3199 silc_command_get_ident(cmd->payload),
3200 silc_server_command_destructor,
3201 silc_server_command_motd,
3202 silc_server_command_dup(cmd));
3203 cmd->pending = TRUE;
3204 silc_command_set_ident(cmd->payload, old_ident);
3205 silc_buffer_free(tmpbuf);
3210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3211 SILC_STATUS_ERR_NO_SUCH_SERVER);
3215 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3218 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3219 SILC_STATUS_OK, ident, 2,
3222 strlen(entry->motd));
3224 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3225 SILC_STATUS_OK, ident, 1,
3228 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3229 packet->data, packet->len, FALSE);
3230 silc_buffer_free(packet);
3231 silc_buffer_free(idp);
3235 silc_server_command_free(cmd);
3238 /* Server side of command UMODE. Client can use this command to set/unset
3239 user mode. Client actually cannot set itself to be as server/router
3240 operator so this can be used only to unset the modes. */
3242 SILC_SERVER_CMD_FUNC(umode)
3244 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3245 SilcServer server = cmd->server;
3246 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3248 unsigned char *tmp_mask;
3250 uint16 ident = silc_command_get_ident(cmd->payload);
3252 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3255 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3257 /* Get the client's mode mask */
3258 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3260 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3261 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3264 SILC_GET32_MSB(mask, tmp_mask);
3270 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3271 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3272 /* Cannot operator mode */
3273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3274 SILC_STATUS_ERR_PERM_DENIED);
3278 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3279 /* Remove the server operator rights */
3280 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3283 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3284 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3285 /* Cannot operator mode */
3286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3287 SILC_STATUS_ERR_PERM_DENIED);
3291 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3292 /* Remove the router operator rights */
3293 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3296 if (mask & SILC_UMODE_GONE) {
3297 client->mode |= SILC_UMODE_GONE;
3299 if (client->mode & SILC_UMODE_GONE)
3300 /* Remove the gone status */
3301 client->mode &= ~SILC_UMODE_GONE;
3304 /* Send UMODE change to primary router */
3305 if (!server->standalone)
3306 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3307 client->id, SILC_ID_CLIENT_LEN,
3310 /* Send command reply to sender */
3311 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3312 SILC_STATUS_OK, ident, 1,
3314 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3315 packet->data, packet->len, FALSE);
3316 silc_buffer_free(packet);
3319 silc_server_command_free(cmd);
3322 /* Checks that client has rights to add or remove channel modes. If any
3323 of the checks fails FALSE is returned. */
3325 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3326 SilcChannelClientEntry client,
3329 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3330 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3332 /* Check whether has rights to change anything */
3333 if (!is_op && !is_fo)
3336 /* Check whether has rights to change everything */
3340 /* We know that client is channel operator, check that they are not
3341 changing anything that requires channel founder rights. Rest of the
3342 modes are available automatically for channel operator. */
3344 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3345 if (is_op && !is_fo)
3348 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3349 if (is_op && !is_fo)
3354 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3355 if (is_op && !is_fo)
3358 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3359 if (is_op && !is_fo)
3364 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3365 if (is_op && !is_fo)
3368 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3369 if (is_op && !is_fo)
3374 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3375 if (is_op && !is_fo)
3378 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3379 if (is_op && !is_fo)
3387 /* Server side command of CMODE. Changes channel mode */
3389 SILC_SERVER_CMD_FUNC(cmode)
3391 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3392 SilcServer server = cmd->server;
3393 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3394 SilcIDListData idata = (SilcIDListData)client;
3395 SilcChannelID *channel_id;
3396 SilcChannelEntry channel;
3397 SilcChannelClientEntry chl;
3398 SilcBuffer packet, cidp;
3399 unsigned char *tmp, *tmp_id, *tmp_mask;
3400 char *cipher = NULL, *hmac = NULL;
3401 uint32 mode_mask, tmp_len, tmp_len2;
3402 uint16 ident = silc_command_get_ident(cmd->payload);
3404 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CMODE, cmd, 2, 7);
3406 /* Get Channel ID */
3407 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3410 SILC_STATUS_ERR_NO_CHANNEL_ID);
3413 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3416 SILC_STATUS_ERR_NO_CHANNEL_ID);
3420 /* Get the channel mode mask */
3421 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3424 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3427 SILC_GET32_MSB(mode_mask, tmp_mask);
3429 /* Get channel entry */
3430 channel = silc_idlist_find_channel_by_id(server->local_list,
3433 channel = silc_idlist_find_channel_by_id(server->global_list,
3436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3437 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3442 /* Check whether this client is on the channel */
3443 if (!silc_server_client_on_channel(client, channel)) {
3444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3445 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3449 /* Get entry to the channel user list */
3450 silc_list_start(channel->user_list);
3451 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3452 if (chl->client == client)
3455 /* Check that client has rights to change any requested channel modes */
3456 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3458 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3463 * Check the modes. Modes that requires nothing special operation are
3467 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3468 /* Channel uses private keys to protect traffic. Client(s) has set the
3469 key locally they want to use, server does not know that key. */
3470 /* Nothing interesting to do here */
3472 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3473 /* The mode is removed and we need to generate and distribute
3474 new channel key. Clients are not using private channel keys
3475 anymore after this. */
3477 /* Re-generate channel key */
3478 silc_server_create_channel_key(server, channel, 0);
3480 /* Send the channel key. This sends it to our local clients and if
3481 we are normal server to our router as well. */
3482 silc_server_send_channel_key(server, NULL, channel,
3483 server->server_type == SILC_ROUTER ?
3484 FALSE : !server->standalone);
3486 cipher = channel->channel_key->cipher->name;
3487 hmac = channel->hmac->hmac->name;
3491 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3492 /* User limit is set on channel */
3495 /* Get user limit */
3496 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3498 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3500 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3504 SILC_GET32_MSB(user_limit, tmp);
3505 channel->user_limit = user_limit;
3508 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3509 /* User limit mode is unset. Remove user limit */
3510 channel->user_limit = 0;
3513 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3514 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3515 /* Passphrase has been set to channel */
3517 /* Get the passphrase */
3518 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3521 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3525 /* Save the passphrase */
3526 channel->passphrase = strdup(tmp);
3529 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3530 /* Passphrase mode is unset. remove the passphrase */
3531 if (channel->passphrase) {
3532 silc_free(channel->passphrase);
3533 channel->passphrase = NULL;
3538 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3539 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3540 /* Cipher to use protect the traffic */
3543 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3545 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3546 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3550 /* Delete old cipher and allocate the new one */
3551 silc_cipher_free(channel->channel_key);
3552 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3553 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3554 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3558 /* Re-generate channel key */
3559 silc_server_create_channel_key(server, channel, 0);
3561 /* Send the channel key. This sends it to our local clients and if
3562 we are normal server to our router as well. */
3563 silc_server_send_channel_key(server, NULL, channel,
3564 server->server_type == SILC_ROUTER ?
3565 FALSE : !server->standalone);
3568 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3569 /* Cipher mode is unset. Remove the cipher and revert back to
3571 cipher = channel->cipher;
3573 /* Delete old cipher and allocate default one */
3574 silc_cipher_free(channel->channel_key);
3575 if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc",
3576 &channel->channel_key)) {
3577 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3578 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3582 /* Re-generate channel key */
3583 silc_server_create_channel_key(server, channel, 0);
3585 /* Send the channel key. This sends it to our local clients and if
3586 we are normal server to our router as well. */
3587 silc_server_send_channel_key(server, NULL, channel,
3588 server->server_type == SILC_ROUTER ?
3589 FALSE : !server->standalone);
3593 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3594 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3595 /* HMAC to use protect the traffic */
3596 unsigned char hash[32];
3599 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3602 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3606 /* Delete old hmac and allocate the new one */
3607 silc_hmac_free(channel->hmac);
3608 if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3609 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3610 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3614 /* Set the HMAC key out of current channel key. The client must do
3616 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3618 silc_hmac_set_key(channel->hmac, hash,
3619 silc_hash_len(channel->hmac->hash));
3620 memset(hash, 0, sizeof(hash));
3623 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3624 /* Hmac mode is unset. Remove the hmac and revert back to
3626 unsigned char hash[32];
3627 hmac = channel->hmac_name;
3629 /* Delete old hmac and allocate default one */
3630 silc_hmac_free(channel->hmac);
3631 if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL,
3633 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3634 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3638 /* Set the HMAC key out of current channel key. The client must do
3640 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3642 silc_hmac_set_key(channel->hmac, hash,
3643 silc_hash_len(channel->hmac->hash));
3644 memset(hash, 0, sizeof(hash));
3648 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3649 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3650 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3651 /* Set the founder authentication */
3652 SilcAuthPayload auth;
3654 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3656 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3657 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3661 auth = silc_auth_payload_parse(tmp, tmp_len);
3663 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3664 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3668 /* Save the public key */
3669 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3670 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3673 channel->founder_method = silc_auth_get_method(auth);
3675 if (channel->founder_method == SILC_AUTH_PASSWORD) {
3676 tmp = silc_auth_get_data(auth, &tmp_len);
3677 channel->founder_passwd =
3678 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3679 memcpy(channel->founder_passwd, tmp, tmp_len);
3680 channel->founder_passwd_len = tmp_len;
3683 silc_auth_payload_free(auth);
3687 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3688 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3689 if (channel->founder_key)
3690 silc_pkcs_public_key_free(channel->founder_key);
3691 if (channel->founder_passwd) {
3692 silc_free(channel->founder_passwd);
3693 channel->founder_passwd = NULL;
3699 /* Finally, set the mode */
3700 channel->mode = mode_mask;
3702 /* Send CMODE_CHANGE notify */
3703 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3704 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3705 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3706 cidp->data, cidp->len,
3708 cipher, cipher ? strlen(cipher) : 0,
3709 hmac, hmac ? strlen(hmac) : 0);
3711 /* Set CMODE notify type to network */
3712 if (!server->standalone)
3713 silc_server_send_notify_cmode(server, server->router->connection,
3714 server->server_type == SILC_ROUTER ?
3715 TRUE : FALSE, channel,
3716 mode_mask, client->id, SILC_ID_CLIENT,
3720 /* Send command reply to sender */
3721 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3722 SILC_STATUS_OK, ident, 1,
3724 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3725 packet->data, packet->len, FALSE);
3727 silc_buffer_free(packet);
3728 silc_free(channel_id);
3732 silc_server_command_free(cmd);
3735 /* Server side of CUMODE command. Changes client's mode on a channel. */
3737 SILC_SERVER_CMD_FUNC(cumode)
3739 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3740 SilcServer server = cmd->server;
3741 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3742 SilcIDListData idata = (SilcIDListData)client;
3743 SilcChannelID *channel_id;
3744 SilcClientID *client_id;
3745 SilcChannelEntry channel;
3746 SilcClientEntry target_client;
3747 SilcChannelClientEntry chl;
3748 SilcBuffer packet, idp;
3749 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3750 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3752 uint16 ident = silc_command_get_ident(cmd->payload);
3754 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 4);
3756 /* Get Channel ID */
3757 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3759 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3760 SILC_STATUS_ERR_NO_CHANNEL_ID);
3763 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3766 SILC_STATUS_ERR_NO_CHANNEL_ID);
3770 /* Get channel entry */
3771 channel = silc_idlist_find_channel_by_id(server->local_list,
3774 channel = silc_idlist_find_channel_by_id(server->global_list,
3777 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3778 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3783 /* Check whether sender is on the channel */
3784 if (!silc_server_client_on_channel(client, channel)) {
3785 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3786 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3790 /* Check that client has rights to change other's rights */
3791 silc_list_start(channel->user_list);
3792 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3793 if (chl->client == client) {
3794 sender_mask = chl->mode;
3799 /* Get the target client's channel mode mask */
3800 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3802 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3803 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3806 SILC_GET32_MSB(target_mask, tmp_mask);
3808 /* Get target Client ID */
3809 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3812 SILC_STATUS_ERR_NO_CLIENT_ID);
3815 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3818 SILC_STATUS_ERR_NO_CLIENT_ID);
3822 /* Get target client's entry */
3823 target_client = silc_idlist_find_client_by_id(server->local_list,
3825 if (!target_client) {
3826 target_client = silc_idlist_find_client_by_id(server->global_list,
3830 if (target_client != client &&
3831 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3832 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3834 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3838 /* Check whether target client is on the channel */
3839 if (target_client != client) {
3840 if (!silc_server_client_on_channel(target_client, channel)) {
3841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3842 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3846 /* Get entry to the channel user list */
3847 silc_list_start(channel->user_list);
3848 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3849 if (chl->client == target_client)
3857 /* If the target client is founder, no one else can change their mode
3859 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3860 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3861 SILC_STATUS_ERR_NOT_YOU);
3865 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3866 /* The client tries to claim the founder rights. */
3867 unsigned char *tmp_auth;
3868 uint32 tmp_auth_len, auth_len;
3871 if (target_client != client) {
3872 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3873 SILC_STATUS_ERR_NOT_YOU);
3877 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3878 !channel->founder_key) {
3879 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3880 SILC_STATUS_ERR_NOT_YOU);
3884 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3886 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3887 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3891 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
3892 (void *)channel->founder_passwd : (void *)channel->founder_key);
3893 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3894 channel->founder_passwd_len : 0);
3896 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
3897 channel->founder_method, auth, auth_len,
3898 idata->hash, client->id, SILC_ID_CLIENT)) {
3899 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3900 SILC_STATUS_ERR_AUTH_FAILED);
3904 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3907 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3908 if (target_client == client) {
3909 /* Remove channel founder rights from itself */
3910 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3913 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3914 SILC_STATUS_ERR_NOT_YOU);
3920 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3921 /* Promote to operator */
3922 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3923 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3924 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3925 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3926 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3930 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3934 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3935 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3936 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3937 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3938 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3942 /* Demote to normal user */
3943 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3948 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3949 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3951 /* Send notify to channel, notify only if mode was actually changed. */
3953 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3954 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3955 idp->data, idp->len,
3959 /* Set CUMODE notify type to network */
3960 if (!server->standalone)
3961 silc_server_send_notify_cumode(server, server->router->connection,
3962 server->server_type == SILC_ROUTER ?
3963 TRUE : FALSE, channel,
3964 target_mask, client->id,
3967 SILC_ID_CLIENT_LEN);
3970 /* Send command reply to sender */
3971 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3972 SILC_STATUS_OK, ident, 2,
3974 3, tmp_id, tmp_len);
3975 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3976 packet->data, packet->len, FALSE);
3978 silc_buffer_free(packet);
3979 silc_free(channel_id);
3980 silc_free(client_id);
3981 silc_buffer_free(idp);
3984 silc_server_command_free(cmd);
3987 /* Server side of KICK command. Kicks client out of channel. */
3989 SILC_SERVER_CMD_FUNC(kick)
3991 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3992 SilcServer server = cmd->server;
3993 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3994 SilcClientEntry target_client;
3995 SilcChannelID *channel_id;
3996 SilcClientID *client_id;
3997 SilcChannelEntry channel;
3998 SilcChannelClientEntry chl;
4001 unsigned char *tmp, *comment;
4003 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
4005 /* Get Channel ID */
4006 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4008 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4009 SILC_STATUS_ERR_NO_CHANNEL_ID);
4012 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4014 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4015 SILC_STATUS_ERR_NO_CHANNEL_ID);
4019 /* Get channel entry */
4020 channel = silc_idlist_find_channel_by_id(server->local_list,
4023 channel = silc_idlist_find_channel_by_id(server->local_list,
4026 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4027 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4032 /* Check whether sender is on the channel */
4033 if (!silc_server_client_on_channel(client, channel)) {
4034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4035 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4039 /* Check that the kicker is channel operator or channel founder */
4040 silc_list_start(channel->user_list);
4041 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4042 if (chl->client == client) {
4043 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4044 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4045 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4052 /* Get target Client ID */
4053 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4055 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4056 SILC_STATUS_ERR_NO_CLIENT_ID);
4059 client_id = silc_id_payload_parse_id(tmp, tmp_len);
4061 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4062 SILC_STATUS_ERR_NO_CLIENT_ID);
4066 /* Get target client's entry */
4067 target_client = silc_idlist_find_client_by_id(server->local_list,
4069 if (!target_client) {
4070 target_client = silc_idlist_find_client_by_id(server->global_list,
4074 /* Check that the target client is not channel founder. Channel founder
4075 cannot be kicked from the channel. */
4076 silc_list_start(channel->user_list);
4077 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4078 if (chl->client == target_client) {
4079 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4080 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4081 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4088 /* Check whether target client is on the channel */
4089 if (!silc_server_client_on_channel(target_client, channel)) {
4090 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4091 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4097 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4101 /* Send command reply to sender */
4102 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4105 /* Send KICKED notify to local clients on the channel */
4106 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4107 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4108 SILC_NOTIFY_TYPE_KICKED,
4110 idp->data, idp->len,
4111 comment, comment ? strlen(comment) : 0);
4112 silc_buffer_free(idp);
4114 /* Remove the client from the channel. If the channel does not exist
4115 after removing the client then the client kicked itself off the channel
4116 and we don't have to send anything after that. */
4117 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4118 target_client, FALSE))
4121 /* Send KICKED notify to primary route */
4122 if (!server->standalone)
4123 silc_server_send_notify_kicked(server, server->router->connection,
4124 server->server_type == SILC_ROUTER ?
4125 TRUE : FALSE, channel,
4126 target_client->id, SILC_ID_CLIENT_LEN,
4129 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4130 /* Re-generate channel key */
4131 silc_server_create_channel_key(server, channel, 0);
4133 /* Send the channel key to the channel. The key of course is not sent
4134 to the client who was kicked off the channel. */
4135 silc_server_send_channel_key(server, target_client->connection, channel,
4136 server->server_type == SILC_ROUTER ?
4137 FALSE : !server->standalone);
4141 silc_server_command_free(cmd);
4144 /* Server side of OPER command. Client uses this comand to obtain server
4145 operator privileges to this server/router. */
4147 SILC_SERVER_CMD_FUNC(oper)
4149 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4150 SilcServer server = cmd->server;
4151 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4152 unsigned char *username, *auth;
4154 SilcServerConfigSectionAdminConnection *admin;
4155 SilcIDListData idata = (SilcIDListData)client;
4157 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
4159 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4162 /* Get the username */
4163 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4165 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4166 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4170 /* Get the admin configuration */
4171 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4172 username, client->nickname);
4174 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4175 username, client->nickname);
4177 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4178 SILC_STATUS_ERR_AUTH_FAILED);
4183 /* Get the authentication payload */
4184 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4186 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4187 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4191 /* Verify the authentication data */
4192 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4193 admin->auth_data, admin->auth_data_len,
4194 idata->hash, client->id, SILC_ID_CLIENT)) {
4195 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4196 SILC_STATUS_ERR_AUTH_FAILED);
4200 /* Client is now server operator */
4201 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4203 /* Send UMODE change to primary router */
4204 if (!server->standalone)
4205 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4206 client->id, SILC_ID_CLIENT_LEN,
4209 /* Send reply to the sender */
4210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4214 silc_server_command_free(cmd);
4217 /* Server side of SILCOPER command. Client uses this comand to obtain router
4218 operator privileges to this router. */
4220 SILC_SERVER_CMD_FUNC(silcoper)
4222 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4223 SilcServer server = cmd->server;
4224 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4225 unsigned char *username, *auth;
4227 SilcServerConfigSectionAdminConnection *admin;
4228 SilcIDListData idata = (SilcIDListData)client;
4230 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4232 if (server->server_type == SILC_SERVER)
4235 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4238 /* Get the username */
4239 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4241 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4242 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4246 /* Get the admin configuration */
4247 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4248 username, client->nickname);
4250 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4251 username, client->nickname);
4253 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4254 SILC_STATUS_ERR_AUTH_FAILED);
4259 /* Get the authentication payload */
4260 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4263 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4267 /* Verify the authentication data */
4268 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4269 admin->auth_data, admin->auth_data_len,
4270 idata->hash, client->id, SILC_ID_CLIENT)) {
4271 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4272 SILC_STATUS_ERR_AUTH_FAILED);
4276 /* Client is now router operator */
4277 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4279 /* Send UMODE change to primary router */
4280 if (!server->standalone)
4281 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4282 client->id, SILC_ID_CLIENT_LEN,
4285 /* Send reply to the sender */
4286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4290 silc_server_command_free(cmd);
4293 /* Server side command of CONNECT. Connects us to the specified remote
4294 server or router. */
4296 SILC_SERVER_CMD_FUNC(connect)
4298 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4299 SilcServer server = cmd->server;
4300 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4301 unsigned char *tmp, *host;
4303 uint32 port = SILC_PORT;
4305 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4307 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4310 /* Check whether client has the permissions. */
4311 if (client->mode == SILC_UMODE_NONE) {
4312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4313 SILC_STATUS_ERR_NO_SERVER_PRIV);
4317 if (server->server_type == SILC_ROUTER &&
4318 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4320 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4324 /* Get the remote server */
4325 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4328 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4333 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4335 SILC_GET32_MSB(port, tmp);
4337 /* Create the connection. It is done with timeout and is async. */
4338 silc_server_create_connection(server, host, port);
4340 /* Send reply to the sender */
4341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4345 silc_server_command_free(cmd);
4348 /* Server side of command BAN. This is used to manage the ban list of the
4349 channel. To add clients and remove clients from the ban list. */
4351 SILC_SERVER_CMD_FUNC(ban)
4353 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4354 SilcServer server = cmd->server;
4355 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4357 SilcChannelEntry channel;
4358 SilcChannelClientEntry chl;
4359 SilcChannelID *channel_id = NULL;
4360 unsigned char *id, *add, *del;
4361 uint32 id_len, tmp_len;
4362 uint16 ident = silc_command_get_ident(cmd->payload);
4364 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4367 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4369 /* Get Channel ID */
4370 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4372 channel_id = silc_id_payload_parse_id(id, id_len);
4374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4375 SILC_STATUS_ERR_NO_CHANNEL_ID);
4380 /* Get channel entry. The server must know about the channel since the
4381 client is expected to be on the channel. */
4382 channel = silc_idlist_find_channel_by_id(server->local_list,
4385 channel = silc_idlist_find_channel_by_id(server->global_list,
4388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4389 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4394 /* Check whether this client is on the channel */
4395 if (!silc_server_client_on_channel(client, channel)) {
4396 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4397 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4401 /* Get entry to the channel user list */
4402 silc_list_start(channel->user_list);
4403 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4404 if (chl->client == client)
4407 /* The client must be at least channel operator. */
4408 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4410 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4414 /* Get the new ban and add it to the ban list */
4415 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4417 if (!channel->ban_list)
4418 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4420 channel->ban_list = silc_realloc(channel->ban_list,
4421 sizeof(*channel->ban_list) *
4423 strlen(channel->ban_list) + 2));
4424 if (add[tmp_len - 1] == ',')
4425 add[tmp_len - 1] = '\0';
4427 strncat(channel->ban_list, add, tmp_len);
4428 strncat(channel->ban_list, ",", 1);
4431 /* Get the ban to be removed and remove it from the list */
4432 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4433 if (del && channel->ban_list) {
4434 char *start, *end, *n;
4436 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4437 silc_free(channel->ban_list);
4438 channel->ban_list = NULL;
4440 start = strstr(channel->ban_list, del);
4441 if (start && strlen(start) >= tmp_len) {
4442 end = start + tmp_len;
4443 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4444 strncat(n, channel->ban_list, start - channel->ban_list);
4445 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4447 silc_free(channel->ban_list);
4448 channel->ban_list = n;
4453 /* Send the BAN notify type to our primary router. */
4454 if (!server->standalone && (add || del))
4455 silc_server_send_notify_ban(server, server->router->connection,
4456 server->server_type == SILC_ROUTER ?
4457 TRUE : FALSE, channel, add, del);
4459 /* Send the reply back to the client */
4460 if (channel->ban_list)
4462 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4463 SILC_STATUS_OK, ident, 2,
4465 3, channel->ban_list,
4466 strlen(channel->ban_list) - 1);
4469 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4470 SILC_STATUS_OK, ident, 1,
4473 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4474 packet->data, packet->len, FALSE);
4476 silc_buffer_free(packet);
4480 silc_free(channel_id);
4481 silc_server_command_free(cmd);
4484 /* Server side command of CLOSE. Closes connection to a specified server. */
4486 SILC_SERVER_CMD_FUNC(close)
4488 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4489 SilcServer server = cmd->server;
4490 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4491 SilcServerEntry server_entry;
4492 SilcSocketConnection sock;
4495 unsigned char *name;
4496 uint32 port = SILC_PORT;
4498 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4500 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4503 /* Check whether client has the permissions. */
4504 if (client->mode == SILC_UMODE_NONE) {
4505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4506 SILC_STATUS_ERR_NO_SERVER_PRIV);
4510 /* Get the remote server */
4511 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4513 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4514 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4519 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4521 SILC_GET32_MSB(port, tmp);
4523 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4525 if (!server_entry) {
4526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4527 SILC_STATUS_ERR_NO_SERVER_ID);
4531 /* Send reply to the sender */
4532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4535 /* Close the connection to the server */
4536 sock = (SilcSocketConnection)server_entry->connection;
4537 silc_server_free_sock_user_data(server, sock);
4538 silc_server_close_connection(server, sock);
4541 silc_server_command_free(cmd);
4544 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4545 active connections. */
4547 SILC_SERVER_CMD_FUNC(shutdown)
4549 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4550 SilcServer server = cmd->server;
4551 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4553 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4555 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4558 /* Check whether client has the permission. */
4559 if (client->mode == SILC_UMODE_NONE) {
4560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4561 SILC_STATUS_ERR_NO_SERVER_PRIV);
4565 /* Send reply to the sender */
4566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4569 /* Then, gracefully, or not, bring the server down. */
4570 silc_server_stop(server);
4574 silc_server_command_free(cmd);
4577 /* Server side command of LEAVE. Removes client from a channel. */
4579 SILC_SERVER_CMD_FUNC(leave)
4581 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4582 SilcServer server = cmd->server;
4583 SilcSocketConnection sock = cmd->sock;
4584 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4585 SilcChannelID *id = NULL;
4586 SilcChannelEntry channel;
4590 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4592 /* Get Channel ID */
4593 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4595 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4596 SILC_STATUS_ERR_NO_CHANNEL_ID);
4599 id = silc_id_payload_parse_id(tmp, len);
4601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4602 SILC_STATUS_ERR_NO_CHANNEL_ID);
4606 /* Get channel entry */
4607 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4609 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4612 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4617 /* Check whether this client is on the channel */
4618 if (!silc_server_client_on_channel(id_entry, channel)) {
4619 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4620 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4624 /* Notify routers that they should remove this client from their list
4625 of clients on the channel. Send LEAVE notify type. */
4626 if (!server->standalone)
4627 silc_server_send_notify_leave(server, server->router->connection,
4628 server->server_type == SILC_ROUTER ?
4629 TRUE : FALSE, channel, id_entry->id,
4630 SILC_ID_CLIENT_LEN);
4632 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4635 /* Remove client from channel */
4636 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4638 /* If the channel does not exist anymore we won't send anything */
4641 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4642 /* Re-generate channel key */
4643 silc_server_create_channel_key(server, channel, 0);
4645 /* Send the channel key */
4646 silc_server_send_channel_key(server, NULL, channel,
4647 server->server_type == SILC_ROUTER ?
4648 FALSE : !server->standalone);
4656 silc_server_command_free(cmd);
4659 /* Server side of command USERS. Resolves clients and their USERS currently
4660 joined on the requested channel. The list of Client ID's and their modes
4661 on the channel is sent back. */
4663 SILC_SERVER_CMD_FUNC(users)
4665 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4666 SilcServer server = cmd->server;
4667 SilcChannelEntry channel;
4670 unsigned char *channel_id;
4671 uint32 channel_id_len;
4672 SilcBuffer client_id_list;
4673 SilcBuffer client_mode_list;
4674 unsigned char lc[4];
4675 uint32 list_count = 0;
4676 uint16 ident = silc_command_get_ident(cmd->payload);
4678 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4680 /* Get Channel ID */
4681 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4683 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4684 SILC_STATUS_ERR_NO_CHANNEL_ID);
4687 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4690 SILC_STATUS_ERR_NO_CHANNEL_ID);
4694 /* If we are server and we don't know about this channel we will send
4695 the command to our router. If we know about the channel then we also
4696 have the list of users already. */
4697 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4699 if (server->server_type == SILC_SERVER && !server->standalone &&
4703 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4704 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4706 /* Send USERS command */
4707 silc_server_packet_send(server, server->router->connection,
4708 SILC_PACKET_COMMAND, cmd->packet->flags,
4709 tmpbuf->data, tmpbuf->len, TRUE);
4711 /* Reprocess this packet after received reply */
4712 silc_server_command_pending(server, SILC_COMMAND_USERS,
4713 silc_command_get_ident(cmd->payload),
4714 silc_server_command_destructor,
4715 silc_server_command_users,
4716 silc_server_command_dup(cmd));
4717 cmd->pending = TRUE;
4718 silc_command_set_ident(cmd->payload, ident);
4720 silc_buffer_free(tmpbuf);
4725 /* We are router and we will check the global list as well. */
4726 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4728 /* Channel really does not exist */
4729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4730 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4735 /* Get the users list */
4736 silc_server_get_users_on_channel(server, channel, &client_id_list,
4737 &client_mode_list, &list_count);
4740 SILC_PUT32_MSB(list_count, lc);
4743 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4744 SILC_STATUS_OK, ident, 4,
4745 2, channel_id, channel_id_len,
4747 4, client_id_list->data,
4748 client_id_list->len,
4749 5, client_mode_list->data,
4750 client_mode_list->len);
4751 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4752 packet->data, packet->len, FALSE);
4754 silc_buffer_free(packet);
4755 silc_buffer_free(client_id_list);
4756 silc_buffer_free(client_mode_list);
4760 silc_server_command_free(cmd);