5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
37 unsigned int arg_type,
39 unsigned int arg_len);
40 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
45 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
49 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
50 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
54 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(connect, CONNECT,
56 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
60 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
63 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
65 SILC_SERVER_CMD(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 unsigned int _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,
280 unsigned short ident,
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,
300 unsigned short ident)
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,
319 unsigned short ident)
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,
373 unsigned int arg_type,
375 unsigned int arg_len)
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 unsigned int *client_id_count,
408 unsigned int 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 unsigned int 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) {
494 unsigned short old_ident;
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 unsigned int clients_count,
532 SilcServer server = cmd->server;
535 SilcBuffer packet, idp, channels;
536 SilcClientEntry entry;
537 SilcCommandStatus status;
538 unsigned short ident = silc_command_get_ident(cmd->payload);
539 char nh[128], uh[128];
540 unsigned char idle[4], mode[4];
541 SilcSocketConnection hsock;
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;
656 int count = 0, clients_count = 0;
657 SilcClientEntry *clients = NULL, entry;
658 SilcClientID **client_id = NULL;
659 unsigned int client_id_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) {
669 unsigned short old_ident;
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;
798 int count = 0, clients_count = 0;
799 SilcClientEntry *clients = NULL, entry;
800 SilcClientID **client_id = NULL;
801 unsigned int client_id_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 unsigned int clients_count)
969 SilcServer server = cmd->server;
971 SilcClientEntry entry;
973 for (i = 0; i < clients_count; i++) {
976 if (!entry->nickname || !entry->username) {
978 unsigned short old_ident;
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 unsigned int 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 unsigned short 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;
1114 int count = 0, clients_count = 0;
1115 SilcClientEntry *clients = NULL;
1118 /* Protocol dictates that we must always send the received WHOWAS request
1119 to our router if we are normal server, so let's do it now unless we
1120 are standalone. We will not send any replies to the client until we
1121 have received reply from the router. */
1122 if (server->server_type == SILC_SERVER &&
1123 !cmd->pending && !server->standalone) {
1125 unsigned short old_ident;
1127 old_ident = silc_command_get_ident(cmd->payload);
1128 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1129 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1131 /* Send WHOWAS command to our router */
1132 silc_server_packet_send(server, (SilcSocketConnection)
1133 server->router->connection,
1134 SILC_PACKET_COMMAND, cmd->packet->flags,
1135 tmpbuf->data, tmpbuf->len, TRUE);
1137 /* Reprocess this packet after received reply from router */
1138 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1139 silc_command_get_ident(cmd->payload),
1140 silc_server_command_destructor,
1141 silc_server_command_whowas,
1142 silc_server_command_dup(cmd));
1143 cmd->pending = TRUE;
1145 silc_command_set_ident(cmd->payload, old_ident);
1147 silc_buffer_free(tmpbuf);
1152 /* We are ready to process the command request. Let's search for the
1153 requested client and send reply to the requesting client. */
1155 /* Parse the whowas request */
1156 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1159 /* Get all clients matching that nickname from local list */
1160 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1162 &clients, &clients_count))
1163 silc_idlist_get_clients_by_hash(server->local_list,
1164 nick, server->md5hash,
1165 &clients, &clients_count);
1167 /* Check global list as well */
1168 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1170 &clients, &clients_count))
1171 silc_idlist_get_clients_by_hash(server->global_list,
1172 nick, server->md5hash,
1173 &clients, &clients_count);
1175 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1180 /* Send the command reply to the client */
1181 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1189 silc_free(server_name);
1195 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1197 SilcServer server = cmd->server;
1198 char *nick = NULL, *server_name = NULL;
1199 int count = 0, clients_count = 0;
1200 SilcClientEntry *clients = NULL;
1203 /* Parse the whowas request */
1204 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1207 /* Process the command request. Let's search for the requested client and
1208 send reply to the requesting server. */
1210 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1212 &clients, &clients_count))
1213 silc_idlist_get_clients_by_hash(server->local_list,
1214 nick, server->md5hash,
1215 &clients, &clients_count);
1217 /* If we are router we will check our global list as well. */
1218 if (server->server_type == SILC_ROUTER) {
1219 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1221 &clients, &clients_count))
1222 silc_idlist_get_clients_by_hash(server->global_list,
1223 nick, server->md5hash,
1224 &clients, &clients_count);
1228 /* Such a client really does not exist in the SILC network. */
1229 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1230 SILC_STATUS_ERR_NO_SUCH_NICK,
1231 3, nick, strlen(nick));
1235 /* Send the command reply to the client */
1236 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1244 silc_free(server_name);
1249 /* Server side of command WHOWAS. */
1251 SILC_SERVER_CMD_FUNC(whowas)
1253 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1256 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1258 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1259 ret = silc_server_command_whowas_from_client(cmd);
1260 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1261 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1262 ret = silc_server_command_whowas_from_server(cmd);
1265 silc_server_command_free(cmd);
1268 /******************************************************************************
1272 ******************************************************************************/
1274 /* Checks that all mandatory fields are present. If not then send WHOIS
1275 request to the server who owns the client. We use WHOIS because we want
1276 to get as much information as possible at once. */
1279 silc_server_command_identify_check(SilcServerCommandContext cmd,
1280 SilcClientEntry *clients,
1281 unsigned int clients_count)
1283 SilcServer server = cmd->server;
1285 SilcClientEntry entry;
1287 for (i = 0; i < clients_count; i++) {
1290 if (!entry || entry->data.registered == FALSE)
1293 if (!entry->nickname) {
1295 unsigned short old_ident;
1300 old_ident = silc_command_get_ident(cmd->payload);
1301 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1302 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1303 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1305 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1306 now anyway so make it a good one. */
1307 silc_server_packet_send(server, entry->router->connection,
1308 SILC_PACKET_COMMAND, cmd->packet->flags,
1309 tmpbuf->data, tmpbuf->len, TRUE);
1311 /* Reprocess this packet after received reply */
1312 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1313 silc_command_get_ident(cmd->payload),
1314 silc_server_command_destructor,
1315 silc_server_command_identify,
1316 silc_server_command_dup(cmd));
1318 cmd->pending = TRUE;
1320 /* Put old data back to the Command Payload we just changed */
1321 silc_command_set_ident(cmd->payload, old_ident);
1322 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1324 silc_buffer_free(tmpbuf);
1333 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1334 SilcClientEntry *clients,
1335 unsigned int clients_count,
1338 SilcServer server = cmd->server;
1341 SilcBuffer packet, idp;
1342 SilcClientEntry entry;
1343 SilcCommandStatus status;
1344 unsigned short ident = silc_command_get_ident(cmd->payload);
1345 char nh[256], uh[256];
1346 SilcSocketConnection hsock;
1349 for (i = 0; i < clients_count; i++)
1350 if (clients[i]->data.registered)
1353 status = SILC_STATUS_OK;
1355 status = SILC_STATUS_LIST_START;
1357 for (i = 0, k = 0; i < clients_count; i++) {
1360 if (entry->data.registered == FALSE) {
1361 if (clients_count == 1) {
1362 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1363 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1364 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1365 2, idp->data, idp->len);
1366 silc_buffer_free(idp);
1372 status = SILC_STATUS_LIST_ITEM;
1374 if (clients_count > 1 && k == clients_count - 1)
1375 status = SILC_STATUS_LIST_END;
1377 if (count && k - 1 == count)
1378 status = SILC_STATUS_LIST_END;
1380 if (count && k - 1 > count)
1383 /* Send IDENTIFY reply */
1384 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1385 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1387 memset(uh, 0, sizeof(uh));
1388 memset(nh, 0, sizeof(nh));
1390 strncat(nh, entry->nickname, strlen(entry->nickname));
1391 if (!strchr(entry->nickname, '@')) {
1392 strncat(nh, "@", 1);
1393 len = entry->router ? strlen(entry->router->server_name) :
1394 strlen(server->server_name);
1395 strncat(nh, entry->router ? entry->router->server_name :
1396 server->server_name, len);
1399 if (!entry->username) {
1400 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1402 2, idp->data, idp->len,
1405 strncat(uh, entry->username, strlen(entry->username));
1406 if (!strchr(entry->username, '@')) {
1407 strncat(uh, "@", 1);
1408 hsock = (SilcSocketConnection)entry->connection;
1409 len = strlen(hsock->hostname);
1410 strncat(uh, hsock->hostname, len);
1413 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1415 2, idp->data, idp->len,
1420 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1421 0, packet->data, packet->len, FALSE);
1423 silc_buffer_free(packet);
1424 silc_buffer_free(idp);
1431 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1433 SilcServer server = cmd->server;
1434 char *nick = NULL, *server_name = NULL;
1435 int count = 0, clients_count = 0;
1436 SilcClientEntry *clients = NULL, entry;
1437 SilcClientID **client_id = NULL;
1438 unsigned int client_id_count = 0;
1441 /* Protocol dictates that we must always send the received IDENTIFY request
1442 to our router if we are normal server, so let's do it now unless we
1443 are standalone. We will not send any replies to the client until we
1444 have received reply from the router. */
1445 if (server->server_type == SILC_SERVER &&
1446 !cmd->pending && !server->standalone) {
1448 unsigned short old_ident;
1450 old_ident = silc_command_get_ident(cmd->payload);
1451 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1452 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1454 /* Send IDENTIFY command to our router */
1455 silc_server_packet_send(server, (SilcSocketConnection)
1456 server->router->connection,
1457 SILC_PACKET_COMMAND, cmd->packet->flags,
1458 tmpbuf->data, tmpbuf->len, TRUE);
1460 /* Reprocess this packet after received reply from router */
1461 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1462 silc_command_get_ident(cmd->payload),
1463 silc_server_command_destructor,
1464 silc_server_command_identify,
1465 silc_server_command_dup(cmd));
1466 cmd->pending = TRUE;
1468 silc_command_set_ident(cmd->payload, old_ident);
1470 silc_buffer_free(tmpbuf);
1475 /* We are ready to process the command request. Let's search for the
1476 requested client and send reply to the requesting client. */
1478 /* Parse the IDENTIFY request */
1479 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1480 &nick, &server_name, &count,
1481 SILC_COMMAND_IDENTIFY))
1484 /* Get all clients matching that ID or nickname from local list */
1485 if (client_id_count) {
1486 /* Check all Client ID's received in the command packet */
1487 for (i = 0; i < client_id_count; i++) {
1488 entry = silc_idlist_find_client_by_id(server->local_list,
1489 client_id[i], NULL);
1491 clients = silc_realloc(clients, sizeof(*clients) *
1492 (clients_count + 1));
1493 clients[clients_count++] = entry;
1497 if (!silc_idlist_get_clients_by_hash(server->local_list,
1498 nick, server->md5hash,
1499 &clients, &clients_count))
1500 silc_idlist_get_clients_by_nickname(server->local_list,
1502 &clients, &clients_count);
1505 /* Check global list as well */
1506 if (client_id_count) {
1507 /* Check all Client ID's received in the command packet */
1508 for (i = 0; i < client_id_count; i++) {
1509 entry = silc_idlist_find_client_by_id(server->global_list,
1510 client_id[i], NULL);
1512 clients = silc_realloc(clients, sizeof(*clients) *
1513 (clients_count + 1));
1514 clients[clients_count++] = entry;
1518 if (!silc_idlist_get_clients_by_hash(server->global_list,
1519 nick, server->md5hash,
1520 &clients, &clients_count))
1521 silc_idlist_get_clients_by_nickname(server->global_list,
1523 &clients, &clients_count);
1527 /* Such a client really does not exist in the SILC network. */
1528 if (!client_id_count) {
1529 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1530 SILC_STATUS_ERR_NO_SUCH_NICK,
1531 3, nick, strlen(nick));
1533 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1534 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1535 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1536 2, idp->data, idp->len);
1537 silc_buffer_free(idp);
1542 /* Check that all mandatory fields are present and request those data
1543 from the server who owns the client if necessary. */
1544 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1549 /* Send the command reply to the client */
1550 silc_server_command_identify_send_reply(cmd, clients, clients_count,
1554 if (client_id_count) {
1555 for (i = 0; i < client_id_count; i++)
1556 silc_free(client_id[i]);
1557 silc_free(client_id);
1564 silc_free(server_name);
1570 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1572 SilcServer server = cmd->server;
1573 char *nick = NULL, *server_name = NULL;
1574 int count = 0, clients_count = 0;
1575 SilcClientEntry *clients = NULL, entry;
1576 SilcClientID **client_id = NULL;
1577 unsigned int client_id_count = 0;
1580 /* Parse the IDENTIFY request */
1581 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1582 &nick, &server_name, &count,
1583 SILC_COMMAND_IDENTIFY))
1586 /* Process the command request. Let's search for the requested client and
1587 send reply to the requesting server. */
1589 if (client_id_count) {
1590 /* Check all Client ID's received in the command packet */
1591 for (i = 0; i < client_id_count; i++) {
1592 entry = silc_idlist_find_client_by_id(server->local_list,
1593 client_id[i], NULL);
1595 clients = silc_realloc(clients, sizeof(*clients) *
1596 (clients_count + 1));
1597 clients[clients_count++] = entry;
1601 if (!silc_idlist_get_clients_by_hash(server->local_list,
1602 nick, server->md5hash,
1603 &clients, &clients_count))
1604 silc_idlist_get_clients_by_nickname(server->local_list,
1606 &clients, &clients_count);
1609 /* If we are router we will check our global list as well. */
1610 if (server->server_type == SILC_ROUTER) {
1611 if (client_id_count) {
1612 /* Check all Client ID's received in the command packet */
1613 for (i = 0; i < client_id_count; i++) {
1614 entry = silc_idlist_find_client_by_id(server->global_list,
1615 client_id[i], NULL);
1617 clients = silc_realloc(clients, sizeof(*clients) *
1618 (clients_count + 1));
1619 clients[clients_count++] = entry;
1623 if (!silc_idlist_get_clients_by_hash(server->global_list,
1624 nick, server->md5hash,
1625 &clients, &clients_count))
1626 silc_idlist_get_clients_by_nickname(server->global_list,
1628 &clients, &clients_count);
1633 /* Such a client really does not exist in the SILC network. */
1634 if (!client_id_count) {
1635 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1636 SILC_STATUS_ERR_NO_SUCH_NICK,
1637 3, nick, strlen(nick));
1639 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1640 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1641 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1642 2, idp->data, idp->len);
1643 silc_buffer_free(idp);
1648 /* Check that all mandatory fields are present and request those data
1649 from the server who owns the client if necessary. */
1650 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1655 /* Send the command reply */
1656 silc_server_command_identify_send_reply(cmd, clients, clients_count, count);
1659 if (client_id_count) {
1660 for (i = 0; i < client_id_count; i++)
1661 silc_free(client_id[i]);
1662 silc_free(client_id);
1669 silc_free(server_name);
1674 SILC_SERVER_CMD_FUNC(identify)
1676 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1679 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1681 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1682 ret = silc_server_command_identify_from_client(cmd);
1683 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1684 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1685 ret = silc_server_command_identify_from_server(cmd);
1688 silc_server_command_free(cmd);
1691 /* Checks string for bad characters and returns TRUE if they are found. */
1693 static int silc_server_command_bad_chars(char *nick)
1695 if (strchr(nick, '\\')) return TRUE;
1696 if (strchr(nick, '\"')) return TRUE;
1697 if (strchr(nick, '´')) return TRUE;
1698 if (strchr(nick, '`')) return TRUE;
1699 if (strchr(nick, '\'')) return TRUE;
1700 if (strchr(nick, '*')) return TRUE;
1701 if (strchr(nick, '/')) return TRUE;
1702 if (strchr(nick, '@')) return TRUE;
1707 /* Server side of command NICK. Sets nickname for user. Setting
1708 nickname causes generation of a new client ID for the client. The
1709 new client ID is sent to the client after changing the nickname. */
1711 SILC_SERVER_CMD_FUNC(nick)
1713 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1714 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1715 SilcServer server = cmd->server;
1716 SilcBuffer packet, nidp, oidp;
1717 SilcClientID *new_id;
1719 unsigned short ident = silc_command_get_ident(cmd->payload);
1721 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1724 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1726 /* Check nickname */
1727 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1728 if (silc_server_command_bad_chars(nick) == TRUE) {
1729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1730 SILC_STATUS_ERR_BAD_NICKNAME);
1734 if (strlen(nick) > 128)
1737 /* Create new Client ID */
1738 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1739 cmd->server->md5hash, nick,
1742 /* Send notify about nickname change to our router. We send the new
1743 ID and ask to replace it with the old one. If we are router the
1744 packet is broadcasted. Send NICK_CHANGE notify. */
1745 if (!server->standalone)
1746 silc_server_send_notify_nick_change(server, server->router->connection,
1747 server->server_type == SILC_SERVER ?
1748 FALSE : TRUE, client->id,
1749 new_id, SILC_ID_CLIENT_LEN);
1751 /* Remove old cache entry */
1752 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1755 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1759 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1760 silc_free(client->id);
1763 /* Save the nickname as this client is our local client */
1764 if (client->nickname)
1765 silc_free(client->nickname);
1767 client->nickname = strdup(nick);
1768 client->id = new_id;
1770 /* Update client cache */
1771 silc_idcache_add(server->local_list->clients, client->nickname,
1772 strlen(client->nickname), SILC_ID_CLIENT, client->id,
1773 (void *)client, TRUE, FALSE);
1775 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1777 /* Send NICK_CHANGE notify to the client's channels */
1778 silc_server_send_notify_on_channels(server, NULL, client,
1779 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1780 oidp->data, oidp->len,
1781 nidp->data, nidp->len);
1783 /* Send the new Client ID as reply command back to client */
1784 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1785 SILC_STATUS_OK, ident, 1,
1786 2, nidp->data, nidp->len);
1787 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1788 0, packet->data, packet->len, FALSE);
1790 silc_buffer_free(packet);
1791 silc_buffer_free(nidp);
1792 silc_buffer_free(oidp);
1795 silc_server_command_free(cmd);
1798 /* Sends the LIST command reply */
1801 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1802 SilcChannelEntry *lch,
1803 unsigned int lch_count,
1804 SilcChannelEntry *gch,
1805 unsigned int gch_count)
1808 SilcBuffer packet, idp;
1809 SilcChannelEntry entry;
1810 SilcCommandStatus status;
1811 unsigned short ident = silc_command_get_ident(cmd->payload);
1813 unsigned char usercount[4];
1816 for (i = 0; i < lch_count; i++)
1817 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1819 for (i = 0; i < gch_count; i++)
1820 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1823 status = SILC_STATUS_OK;
1824 if ((lch_count + gch_count) > 1)
1825 status = SILC_STATUS_LIST_START;
1828 for (i = 0; i < lch_count; i++) {
1835 status = SILC_STATUS_LIST_ITEM;
1837 if (i == lch_count - 1 && gch_count)
1839 if (lch_count > 1 && i == lch_count - 1)
1840 status = SILC_STATUS_LIST_END;
1842 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1844 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1845 topic = "*private*";
1846 memset(usercount, 0, sizeof(usercount));
1848 topic = entry->topic;
1849 users = silc_list_count(entry->user_list);
1850 SILC_PUT32_MSB(users, usercount);
1853 /* Send the reply */
1856 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1858 2, idp->data, idp->len,
1859 3, entry->channel_name,
1860 strlen(entry->channel_name),
1861 4, topic, strlen(topic),
1865 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1867 2, idp->data, idp->len,
1868 3, entry->channel_name,
1869 strlen(entry->channel_name),
1871 silc_server_packet_send(cmd->server, cmd->sock,
1872 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1873 packet->len, FALSE);
1874 silc_buffer_free(packet);
1875 silc_buffer_free(idp);
1878 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1881 for (i = 0; i < gch_count; i++) {
1888 status = SILC_STATUS_LIST_ITEM;
1890 if (gch_count > 1 && i == lch_count - 1)
1891 status = SILC_STATUS_LIST_END;
1893 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1895 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1896 topic = "*private*";
1897 memset(usercount, 0, sizeof(usercount));
1899 topic = entry->topic;
1900 users = silc_list_count(entry->user_list);
1901 SILC_PUT32_MSB(users, usercount);
1904 /* Send the reply */
1907 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1909 2, idp->data, idp->len,
1910 3, entry->channel_name,
1911 strlen(entry->channel_name),
1912 4, topic, strlen(topic),
1916 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1918 2, idp->data, idp->len,
1919 3, entry->channel_name,
1920 strlen(entry->channel_name),
1922 silc_server_packet_send(cmd->server, cmd->sock,
1923 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1924 packet->len, FALSE);
1925 silc_buffer_free(packet);
1926 silc_buffer_free(idp);
1930 /* Server side of LIST command. This lists the channel of the requested
1931 server. Secret channels are not listed. */
1933 SILC_SERVER_CMD_FUNC(list)
1935 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1936 SilcServer server = cmd->server;
1937 SilcChannelID *channel_id = NULL;
1939 unsigned int tmp_len;
1940 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1941 unsigned int lch_count = 0, gch_count = 0;
1943 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1945 /* Get Channel ID */
1946 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1948 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1951 SILC_STATUS_ERR_NO_CHANNEL_ID);
1956 /* Get the channels from local list */
1957 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1960 /* Get the channels from global list if we are router */
1961 if (server->server_type == SILC_ROUTER)
1962 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1965 /* Send the reply */
1966 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
1967 gchannels, gch_count);
1970 silc_server_command_free(cmd);
1973 /* Server side of TOPIC command. Sets topic for channel and/or returns
1974 current topic to client. */
1976 SILC_SERVER_CMD_FUNC(topic)
1978 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1979 SilcServer server = cmd->server;
1980 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1981 SilcChannelID *channel_id;
1982 SilcChannelEntry channel;
1983 SilcChannelClientEntry chl;
1984 SilcBuffer packet, idp;
1986 unsigned int argc, tmp_len;
1987 unsigned short ident = silc_command_get_ident(cmd->payload);
1989 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1991 argc = silc_argument_get_arg_num(cmd->args);
1993 /* Get Channel ID */
1994 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1996 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1997 SILC_STATUS_ERR_NO_CHANNEL_ID);
2000 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2002 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2003 SILC_STATUS_ERR_NO_CHANNEL_ID);
2007 /* Check whether the channel exists */
2008 channel = silc_idlist_find_channel_by_id(server->local_list,
2011 channel = silc_idlist_find_channel_by_id(server->global_list,
2014 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2015 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2022 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2024 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2025 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2029 if (strlen(tmp) > 256) {
2030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2031 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2035 /* See whether has rights to change topic */
2036 silc_list_start(channel->user_list);
2037 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2038 if (chl->client == client)
2041 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2042 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2044 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2049 /* Set the topic for channel */
2051 silc_free(channel->topic);
2052 channel->topic = strdup(tmp);
2054 /* Send TOPIC_SET notify type to the network */
2055 if (!server->standalone)
2056 silc_server_send_notify_topic_set(server, server->router->connection,
2057 server->server_type == SILC_ROUTER ?
2058 TRUE : FALSE, channel, client->id,
2059 SILC_ID_CLIENT_LEN, channel->topic);
2061 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2063 /* Send notify about topic change to all clients on the channel */
2064 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2065 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2066 idp->data, idp->len,
2067 channel->topic, strlen(channel->topic));
2068 silc_buffer_free(idp);
2071 /* Send the topic to client as reply packet */
2072 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2074 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2075 SILC_STATUS_OK, ident, 2,
2076 2, idp->data, idp->len,
2078 strlen(channel->topic));
2080 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2081 SILC_STATUS_OK, ident, 1,
2082 2, idp->data, idp->len);
2083 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2084 0, packet->data, packet->len, FALSE);
2086 silc_buffer_free(packet);
2087 silc_buffer_free(idp);
2088 silc_free(channel_id);
2091 silc_server_command_free(cmd);
2094 /* Server side of INVITE command. Invites some client to join some channel.
2095 This command is also used to manage the invite list of the channel. */
2097 SILC_SERVER_CMD_FUNC(invite)
2099 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2100 SilcServer server = cmd->server;
2101 SilcSocketConnection sock = cmd->sock, dest_sock;
2102 SilcChannelClientEntry chl;
2103 SilcClientEntry sender, dest;
2104 SilcClientID *dest_id = NULL;
2105 SilcChannelEntry channel;
2106 SilcChannelID *channel_id = NULL;
2107 SilcIDListData idata;
2108 SilcBuffer idp, idp2, packet;
2109 unsigned char *tmp, *add, *del;
2111 unsigned short ident = silc_command_get_ident(cmd->payload);
2113 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2115 /* Get Channel ID */
2116 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2118 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2119 SILC_STATUS_ERR_NO_CHANNEL_ID);
2122 channel_id = silc_id_payload_parse_id(tmp, len);
2124 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2125 SILC_STATUS_ERR_NO_CHANNEL_ID);
2129 /* Get the channel entry */
2130 channel = silc_idlist_find_channel_by_id(server->local_list,
2133 channel = silc_idlist_find_channel_by_id(server->global_list,
2136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2137 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2142 /* Check whether the sender of this command is on the channel. */
2143 sender = (SilcClientEntry)sock->user_data;
2144 if (!silc_server_client_on_channel(sender, channel)) {
2145 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2146 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2150 /* Check whether the channel is invite-only channel. If yes then the
2151 sender of this command must be at least channel operator. */
2152 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2153 silc_list_start(channel->user_list);
2154 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2155 if (chl->client == sender) {
2156 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2157 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2158 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2165 /* Get destination client ID */
2166 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2170 dest_id = silc_id_payload_parse_id(tmp, len);
2172 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2173 SILC_STATUS_ERR_NO_CLIENT_ID);
2177 /* Get the client entry */
2178 dest = silc_server_get_client_resolve(server, dest_id);
2180 if (server->server_type == SILC_ROUTER) {
2181 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2182 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2186 /* The client info is being resolved. Reprocess this packet after
2187 receiving the reply to the query. */
2188 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2190 silc_server_command_destructor,
2191 silc_server_command_invite,
2192 silc_server_command_dup(cmd));
2193 cmd->pending = TRUE;
2194 silc_free(channel_id);
2199 /* Check whether the requested client is already on the channel. */
2200 if (silc_server_client_on_channel(dest, channel)) {
2201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2202 SILC_STATUS_ERR_USER_ON_CHANNEL);
2206 /* Get route to the client */
2207 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2209 memset(invite, 0, sizeof(invite));
2210 strncat(invite, dest->nickname, strlen(dest->nickname));
2211 strncat(invite, "!", 1);
2212 strncat(invite, dest->username, strlen(dest->username));
2213 if (!strchr(dest->username, '@')) {
2214 strncat(invite, "@", 1);
2215 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2218 len = strlen(invite);
2219 if (!channel->invite_list)
2220 channel->invite_list = silc_calloc(len + 2,
2221 sizeof(*channel->invite_list));
2223 channel->invite_list = silc_realloc(channel->invite_list,
2224 sizeof(*channel->invite_list) *
2226 strlen(channel->invite_list) + 2));
2227 strncat(channel->invite_list, invite, len);
2228 strncat(channel->invite_list, ",", 1);
2230 /* Send notify to the client that is invited to the channel */
2231 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2232 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2233 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2235 SILC_NOTIFY_TYPE_INVITE, 3,
2236 idp->data, idp->len,
2237 channel->channel_name,
2238 strlen(channel->channel_name),
2239 idp2->data, idp2->len);
2240 silc_buffer_free(idp);
2241 silc_buffer_free(idp2);
2244 /* Add the client to the invite list of the channel */
2245 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2247 if (!channel->invite_list)
2248 channel->invite_list = silc_calloc(len + 2,
2249 sizeof(*channel->invite_list));
2251 channel->invite_list = silc_realloc(channel->invite_list,
2252 sizeof(*channel->invite_list) *
2254 strlen(channel->invite_list) + 2));
2255 if (add[len - 1] == ',')
2256 add[len - 1] = '\0';
2258 strncat(channel->invite_list, add, len);
2259 strncat(channel->invite_list, ",", 1);
2262 /* Get the invite to be removed and remove it from the list */
2263 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2264 if (del && channel->invite_list) {
2265 char *start, *end, *n;
2267 if (!strncmp(channel->invite_list, del,
2268 strlen(channel->invite_list) - 1)) {
2269 silc_free(channel->invite_list);
2270 channel->invite_list = NULL;
2272 start = strstr(channel->invite_list, del);
2273 if (start && strlen(start) >= len) {
2275 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2276 strncat(n, channel->invite_list, start - channel->invite_list);
2277 strncat(n, end + 1, ((channel->invite_list +
2278 strlen(channel->invite_list)) - end) - 1);
2279 silc_free(channel->invite_list);
2280 channel->invite_list = n;
2285 /* Send notify to the primary router */
2286 if (!server->standalone)
2287 silc_server_send_notify_invite(server, server->router->connection,
2288 server->server_type == SILC_ROUTER ?
2289 TRUE : FALSE, channel,
2290 sender->id, SILC_ID_CLIENT_LEN,
2293 /* Send command reply */
2294 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2295 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2296 SILC_STATUS_OK, ident, 2,
2298 3, channel->invite_list,
2299 channel->invite_list ?
2300 strlen(channel->invite_list) :
2302 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2303 packet->data, packet->len, FALSE);
2304 silc_buffer_free(packet);
2310 silc_free(channel_id);
2311 silc_server_command_free(cmd);
2316 SilcSocketConnection sock;
2320 /* Quits connection to client. This gets called if client won't
2321 close the connection even when it has issued QUIT command. */
2323 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2325 QuitInternal q = (QuitInternal)context;
2327 /* Free all client specific data, such as client entry and entires
2328 on channels this client may be on. */
2329 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2331 q->sock->user_data = NULL;
2333 /* Close the connection on our side */
2334 silc_server_close_connection(q->server, q->sock);
2336 silc_free(q->signoff);
2340 /* Quits SILC session. This is the normal way to disconnect client. */
2342 SILC_SERVER_CMD_FUNC(quit)
2344 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2345 SilcServer server = cmd->server;
2346 SilcSocketConnection sock = cmd->sock;
2348 unsigned char *tmp = NULL;
2349 unsigned int len = 0;
2351 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2353 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2356 /* Get destination ID */
2357 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2361 q = silc_calloc(1, sizeof(*q));
2364 q->signoff = tmp ? strdup(tmp) : NULL;
2366 /* We quit the connection with little timeout */
2367 silc_task_register(server->timeout_queue, sock->sock,
2368 silc_server_command_quit_cb, (void *)q,
2369 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2372 silc_server_command_free(cmd);
2375 /* Server side of command KILL. This command is used by router operator
2376 to remove an client from the SILC Network temporarily. */
2378 SILC_SERVER_CMD_FUNC(kill)
2380 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2381 SilcServer server = cmd->server;
2382 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2383 SilcClientEntry remote_client;
2384 SilcClientID *client_id;
2385 unsigned char *tmp, *comment;
2386 unsigned int tmp_len, tmp_len2;
2388 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2390 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2393 /* KILL command works only on router */
2394 if (server->server_type != SILC_ROUTER) {
2395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2396 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2400 /* Check whether client has the permissions. */
2401 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2403 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2407 /* Get the client ID */
2408 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2411 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2414 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2416 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2417 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2421 /* Get the client entry */
2422 remote_client = silc_idlist_find_client_by_id(server->local_list,
2424 if (!remote_client) {
2425 remote_client = silc_idlist_find_client_by_id(server->global_list,
2427 if (!remote_client) {
2428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2429 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2435 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2439 /* Send reply to the sender */
2440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2443 /* Send the KILL notify packets. First send it to the channel, then
2444 to our primary router and then directly to the client who is being
2445 killed right now. */
2447 /* Send KILLED notify to the channels. It is not sent to the client
2448 as it will be sent differently destined directly to the client and not
2450 silc_server_send_notify_on_channels(server, remote_client,
2451 remote_client, SILC_NOTIFY_TYPE_KILLED,
2454 comment, comment ? tmp_len2 : 0);
2456 /* Send KILLED notify to primary route */
2457 if (!server->standalone)
2458 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2459 remote_client->id, SILC_ID_CLIENT_LEN,
2462 /* Send KILLED notify to the client directly */
2463 silc_server_send_notify_killed(server, remote_client->connection ?
2464 remote_client->connection :
2465 remote_client->router->connection, FALSE,
2466 remote_client->id, SILC_ID_CLIENT_LEN,
2469 /* Remove the client from all channels. This generates new keys to the
2470 channels as well. */
2471 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2474 /* Remove the client entry, If it is locally connected then we will also
2475 disconnect the client here */
2476 if (remote_client->data.registered && remote_client->connection) {
2477 /* Remove locally conneted client */
2478 SilcSocketConnection sock = remote_client->connection;
2479 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2480 silc_server_close_connection(server, sock);
2482 /* Remove remote client */
2483 if (!silc_idlist_del_client(server->global_list, remote_client))
2484 silc_idlist_del_client(server->local_list, remote_client);
2488 silc_server_command_free(cmd);
2491 /* Server side of command INFO. This sends information about us to
2492 the client. If client requested specific server we will send the
2493 command to that server. */
2495 SILC_SERVER_CMD_FUNC(info)
2497 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2498 SilcServer server = cmd->server;
2499 SilcBuffer packet, idp;
2501 unsigned int tmp_len;
2502 char *dest_server, *server_info = NULL, *server_name;
2503 unsigned short ident = silc_command_get_ident(cmd->payload);
2504 SilcServerEntry entry = NULL;
2505 SilcServerID *server_id = NULL;
2507 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 0, 2);
2509 /* Get server name */
2510 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2513 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2515 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2517 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2518 SILC_STATUS_ERR_NO_SERVER_ID);
2524 /* Check whether we have this server cached */
2525 entry = silc_idlist_find_server_by_id(server->local_list,
2528 entry = silc_idlist_find_server_by_id(server->global_list,
2530 if (!entry && server->server_type == SILC_ROUTER) {
2531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2532 SILC_STATUS_ERR_NO_SUCH_SERVER);
2538 if ((!dest_server && !server_id) ||
2539 (dest_server && !cmd->pending &&
2540 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2541 /* Send our reply */
2542 char info_string[256];
2544 memset(info_string, 0, sizeof(info_string));
2545 snprintf(info_string, sizeof(info_string),
2546 "location: %s server: %s admin: %s <%s>",
2547 server->config->admin_info->location,
2548 server->config->admin_info->server_type,
2549 server->config->admin_info->admin_name,
2550 server->config->admin_info->admin_email);
2552 server_info = info_string;
2553 entry = server->id_entry;
2555 /* Check whether we have this server cached */
2556 if (!entry && dest_server) {
2557 entry = silc_idlist_find_server_by_name(server->global_list,
2560 entry = silc_idlist_find_server_by_name(server->local_list,
2565 if (!cmd->pending &&
2566 server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2567 /* Send to the server */
2569 unsigned short old_ident;
2571 old_ident = silc_command_get_ident(cmd->payload);
2572 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2573 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2575 silc_server_packet_send(server, entry->connection,
2576 SILC_PACKET_COMMAND, cmd->packet->flags,
2577 tmpbuf->data, tmpbuf->len, TRUE);
2579 /* Reprocess this packet after received reply from router */
2580 silc_server_command_pending(server, SILC_COMMAND_INFO,
2581 silc_command_get_ident(cmd->payload),
2582 silc_server_command_destructor,
2583 silc_server_command_info,
2584 silc_server_command_dup(cmd));
2585 cmd->pending = TRUE;
2586 silc_command_set_ident(cmd->payload, old_ident);
2587 silc_buffer_free(tmpbuf);
2591 if (!entry && !cmd->pending && !server->standalone) {
2592 /* Send to the primary router */
2594 unsigned short old_ident;
2596 old_ident = silc_command_get_ident(cmd->payload);
2597 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2598 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2600 silc_server_packet_send(server, server->router->connection,
2601 SILC_PACKET_COMMAND, cmd->packet->flags,
2602 tmpbuf->data, tmpbuf->len, TRUE);
2604 /* Reprocess this packet after received reply from router */
2605 silc_server_command_pending(server, SILC_COMMAND_INFO,
2606 silc_command_get_ident(cmd->payload),
2607 silc_server_command_destructor,
2608 silc_server_command_info,
2609 silc_server_command_dup(cmd));
2610 cmd->pending = TRUE;
2611 silc_command_set_ident(cmd->payload, old_ident);
2612 silc_buffer_free(tmpbuf);
2618 silc_free(server_id);
2621 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2622 SILC_STATUS_ERR_NO_SUCH_SERVER);
2626 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2628 server_info = entry->server_info;
2629 server_name = entry->server_name;
2631 /* Send the reply */
2632 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2633 SILC_STATUS_OK, ident, 3,
2634 2, idp->data, idp->len,
2636 strlen(server_name),
2638 strlen(server_info));
2639 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2640 packet->data, packet->len, FALSE);
2642 silc_buffer_free(packet);
2643 silc_buffer_free(idp);
2646 silc_server_command_free(cmd);
2649 /* Server side of command PING. This just replies to the ping. */
2651 SILC_SERVER_CMD_FUNC(ping)
2653 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2654 SilcServer server = cmd->server;
2659 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2662 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2664 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2665 SILC_STATUS_ERR_NO_SERVER_ID);
2668 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2672 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2673 /* Send our reply */
2674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2677 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2678 SILC_STATUS_ERR_NO_SUCH_SERVER);
2685 silc_server_command_free(cmd);
2688 /* Internal routine to join channel. The channel sent to this function
2689 has been either created or resolved from ID lists. This joins the sent
2690 client to the channel. */
2692 static void silc_server_command_join_channel(SilcServer server,
2693 SilcServerCommandContext cmd,
2694 SilcChannelEntry channel,
2695 SilcClientID *client_id,
2699 SilcSocketConnection sock = cmd->sock;
2701 unsigned int tmp_len, user_count;
2702 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2703 SilcClientEntry client;
2704 SilcChannelClientEntry chl;
2705 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2706 unsigned short ident = silc_command_get_ident(cmd->payload);
2709 SILC_LOG_DEBUG(("Start"));
2714 /* Get the client entry */
2715 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2716 client = (SilcClientEntry)sock->user_data;
2718 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2725 * Check channel modes
2728 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2729 strncat(check, client->nickname, strlen(client->nickname));
2730 if (!strchr(client->nickname, '@')) {
2731 strncat(check, "@", 1);
2732 strncat(check, server->server_name, strlen(server->server_name));
2734 strncat(check, "!", 1);
2735 strncat(check, client->username, strlen(client->username));
2736 if (!strchr(client->username, '@')) {
2737 strncat(check, "@", 1);
2738 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2742 /* Check invite list if channel is invite-only channel */
2743 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
2744 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2745 if (!channel->invite_list) {
2746 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2747 SILC_STATUS_ERR_NOT_INVITED);
2751 if (!silc_string_match(channel->invite_list, check)) {
2752 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2753 SILC_STATUS_ERR_NOT_INVITED);
2758 /* Check ban list if it exists. If the client's nickname, server,
2759 username and/or hostname is in the ban list the access to the
2760 channel is denied. */
2761 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2762 if (silc_string_match(channel->ban_list, check)) {
2763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2764 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2769 /* Get passphrase */
2770 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2772 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2773 memcpy(passphrase, tmp, tmp_len);
2776 /* Check the channel passphrase if set. */
2777 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2778 if (!passphrase || memcmp(channel->passphrase, passphrase,
2779 strlen(channel->passphrase))) {
2780 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2781 SILC_STATUS_ERR_BAD_PASSWORD);
2786 /* Check user count limit if set. */
2787 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2788 if (silc_list_count(channel->user_list) + 1 >
2789 channel->user_limit) {
2790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2791 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2797 * Client is allowed to join to the channel. Make it happen.
2800 /* Check whether the client already is on the channel */
2801 if (silc_server_client_on_channel(client, channel)) {
2802 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2803 SILC_STATUS_ERR_USER_ON_CHANNEL);
2807 /* Generate new channel key as protocol dictates */
2808 if ((!created && silc_list_count(channel->user_list) > 0) ||
2809 !channel->channel_key)
2810 silc_server_create_channel_key(server, channel, 0);
2812 /* Send the channel key. This is broadcasted to the channel but is not
2813 sent to the client who is joining to the channel. */
2814 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2815 silc_server_send_channel_key(server, NULL, channel,
2816 server->server_type == SILC_ROUTER ?
2817 FALSE : !server->standalone);
2819 /* Join the client to the channel by adding it to channel's user list.
2820 Add also the channel to client entry's channels list for fast cross-
2822 chl = silc_calloc(1, sizeof(*chl));
2824 chl->client = client;
2825 chl->channel = channel;
2826 silc_list_add(channel->user_list, chl);
2827 silc_list_add(client->channels, chl);
2829 /* Get users on the channel */
2830 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2833 /* Encode Client ID Payload of the original client who wants to join */
2834 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2836 /* Encode command reply packet */
2837 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2838 SILC_PUT32_MSB(channel->mode, mode);
2839 SILC_PUT32_MSB(created, tmp2);
2840 SILC_PUT32_MSB(user_count, tmp3);
2842 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2843 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2844 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2845 strlen(channel->channel_key->
2847 channel->channel_key->cipher->name,
2848 channel->key_len / 8, channel->key);
2853 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2854 SILC_STATUS_OK, ident, 13,
2855 2, channel->channel_name,
2856 strlen(channel->channel_name),
2857 3, chidp->data, chidp->len,
2858 4, clidp->data, clidp->len,
2861 7, keyp ? keyp->data : NULL,
2862 keyp ? keyp->len : 0,
2863 8, channel->ban_list,
2865 strlen(channel->ban_list) : 0,
2866 9, channel->invite_list,
2867 channel->invite_list ?
2868 strlen(channel->invite_list) : 0,
2871 strlen(channel->topic) : 0,
2872 11, channel->hmac->hmac->name,
2873 strlen(channel->hmac->hmac->name),
2875 13, user_list->data, user_list->len,
2876 14, mode_list->data,
2879 /* Send command reply */
2880 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2881 reply->data, reply->len, FALSE);
2883 if (!cmd->pending) {
2884 /* Send JOIN notify to locally connected clients on the channel */
2885 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2886 SILC_NOTIFY_TYPE_JOIN, 2,
2887 clidp->data, clidp->len,
2888 chidp->data, chidp->len);
2890 /* Send JOIN notify packet to our primary router */
2891 if (!server->standalone)
2892 silc_server_send_notify_join(server, server->router->connection,
2893 server->server_type == SILC_ROUTER ?
2894 TRUE : FALSE, channel, client->id,
2895 SILC_ID_CLIENT_LEN);
2898 silc_buffer_free(reply);
2899 silc_buffer_free(clidp);
2900 silc_buffer_free(chidp);
2901 silc_buffer_free(keyp);
2902 silc_buffer_free(user_list);
2903 silc_buffer_free(mode_list);
2907 silc_free(passphrase);
2910 /* Server side of command JOIN. Joins client into requested channel. If
2911 the channel does not exist it will be created. */
2913 SILC_SERVER_CMD_FUNC(join)
2915 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2916 SilcServer server = cmd->server;
2918 char *tmp, *channel_name = NULL, *cipher, *hmac;
2919 SilcChannelEntry channel;
2920 unsigned int umode = 0;
2921 int created = FALSE;
2922 SilcClientID *client_id;
2924 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2926 /* Get channel name */
2927 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2930 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2935 if (strlen(channel_name) > 256)
2936 channel_name[255] = '\0';
2938 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2939 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2940 SILC_STATUS_ERR_BAD_CHANNEL);
2941 silc_free(channel_name);
2945 /* Get Client ID of the client who is joining to the channel */
2946 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2949 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2952 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2955 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2959 /* Get cipher and hmac name */
2960 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2961 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2963 /* See if the channel exists */
2964 channel = silc_idlist_find_channel_by_name(server->local_list,
2965 channel_name, NULL);
2967 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2968 /* If this is coming from client the Client ID in the command packet must
2969 be same as the client's ID. */
2970 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2971 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2972 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2974 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2979 if (!channel || !channel->id) {
2980 /* Channel not found */
2982 /* If we are standalone server we don't have a router, we just create
2983 the channel by ourselves. */
2984 if (server->standalone) {
2985 channel = silc_server_create_new_channel(server, server->id, cipher,
2986 hmac, channel_name, TRUE);
2988 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2989 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2993 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2998 /* The channel does not exist on our server. If we are normal server
2999 we will send JOIN command to our router which will handle the
3000 joining procedure (either creates the channel if it doesn't exist
3001 or joins the client to it). */
3002 if (server->server_type == SILC_SERVER) {
3004 unsigned short old_ident;
3006 old_ident = silc_command_get_ident(cmd->payload);
3007 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3008 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3010 /* Send JOIN command to our router */
3011 silc_server_packet_send(server, (SilcSocketConnection)
3012 server->router->connection,
3013 SILC_PACKET_COMMAND, cmd->packet->flags,
3014 tmpbuf->data, tmpbuf->len, TRUE);
3016 /* Reprocess this packet after received reply from router */
3017 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3018 silc_command_get_ident(cmd->payload),
3019 silc_server_command_destructor,
3020 silc_server_command_join,
3021 silc_server_command_dup(cmd));
3022 cmd->pending = TRUE;
3026 /* We are router and the channel does not seem exist so we will check
3027 our global list as well for the channel. */
3028 channel = silc_idlist_find_channel_by_name(server->global_list,
3029 channel_name, NULL);
3031 /* Channel really does not exist, create it */
3032 channel = silc_server_create_new_channel(server, server->id, cipher,
3033 hmac, channel_name, TRUE);
3035 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3036 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3040 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3047 /* Channel not found */
3049 /* If the command came from router and/or we are normal server then
3050 something went wrong with the joining as the channel was not found.
3051 We can't do anything else but ignore this. */
3052 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3053 server->server_type == SILC_SERVER)
3056 /* We are router and the channel does not seem exist so we will check
3057 our global list as well for the channel. */
3058 channel = silc_idlist_find_channel_by_name(server->global_list,
3059 channel_name, NULL);
3061 /* Channel really does not exist, create it */
3062 channel = silc_server_create_new_channel(server, server->id, cipher,
3063 hmac, channel_name, TRUE);
3065 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3066 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3070 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3076 /* If the channel does not have global users and is also empty it means the
3077 channel was created globally (by our router) and the client will be the
3078 channel founder and operator. */
3079 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3080 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3081 created = TRUE; /* Created globally by our router */
3084 /* Join to the channel */
3085 silc_server_command_join_channel(server, cmd, channel, client_id,
3088 silc_free(client_id);
3091 silc_server_command_free(cmd);
3094 /* Server side of command MOTD. Sends server's current "message of the
3095 day" to the client. */
3097 SILC_SERVER_CMD_FUNC(motd)
3099 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3100 SilcServer server = cmd->server;
3101 SilcBuffer packet, idp;
3102 char *motd, *dest_server;
3104 unsigned short ident = silc_command_get_ident(cmd->payload);
3106 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3108 /* Get server name */
3109 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3111 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3112 SILC_STATUS_ERR_NO_SUCH_SERVER);
3116 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3119 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3121 if (server->config && server->config->motd &&
3122 server->config->motd->motd_file) {
3124 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3129 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3130 SILC_STATUS_OK, ident, 2,
3136 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3137 SILC_STATUS_OK, ident, 1,
3141 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3142 packet->data, packet->len, FALSE);
3143 silc_buffer_free(packet);
3144 silc_buffer_free(idp);
3146 SilcServerEntry entry;
3148 /* Check whether we have this server cached */
3149 entry = silc_idlist_find_server_by_name(server->global_list,
3152 entry = silc_idlist_find_server_by_name(server->local_list,
3156 if (server->server_type == SILC_ROUTER && !cmd->pending &&
3157 entry && !entry->motd) {
3158 /* Send to the server */
3160 unsigned short old_ident;
3162 old_ident = silc_command_get_ident(cmd->payload);
3163 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3164 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3166 silc_server_packet_send(server, entry->connection,
3167 SILC_PACKET_COMMAND, cmd->packet->flags,
3168 tmpbuf->data, tmpbuf->len, TRUE);
3170 /* Reprocess this packet after received reply from router */
3171 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3172 silc_command_get_ident(cmd->payload),
3173 silc_server_command_destructor,
3174 silc_server_command_motd,
3175 silc_server_command_dup(cmd));
3176 cmd->pending = TRUE;
3177 silc_command_set_ident(cmd->payload, old_ident);
3178 silc_buffer_free(tmpbuf);
3182 if (!entry && !cmd->pending && !server->standalone) {
3183 /* Send to the primary router */
3185 unsigned short old_ident;
3187 old_ident = silc_command_get_ident(cmd->payload);
3188 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3189 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3191 silc_server_packet_send(server, server->router->connection,
3192 SILC_PACKET_COMMAND, cmd->packet->flags,
3193 tmpbuf->data, tmpbuf->len, TRUE);
3195 /* Reprocess this packet after received reply from router */
3196 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3197 silc_command_get_ident(cmd->payload),
3198 silc_server_command_destructor,
3199 silc_server_command_motd,
3200 silc_server_command_dup(cmd));
3201 cmd->pending = TRUE;
3202 silc_command_set_ident(cmd->payload, old_ident);
3203 silc_buffer_free(tmpbuf);
3208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3209 SILC_STATUS_ERR_NO_SUCH_SERVER);
3213 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3216 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3217 SILC_STATUS_OK, ident, 2,
3220 strlen(entry->motd));
3222 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3223 SILC_STATUS_OK, ident, 1,
3226 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3227 packet->data, packet->len, FALSE);
3228 silc_buffer_free(packet);
3229 silc_buffer_free(idp);
3233 silc_server_command_free(cmd);
3236 /* Server side of command UMODE. Client can use this command to set/unset
3237 user mode. Client actually cannot set itself to be as server/router
3238 operator so this can be used only to unset the modes. */
3240 SILC_SERVER_CMD_FUNC(umode)
3242 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3243 SilcServer server = cmd->server;
3244 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3246 unsigned char *tmp_mask;
3248 unsigned short ident = silc_command_get_ident(cmd->payload);
3250 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3253 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3255 /* Get the client's mode mask */
3256 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3259 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3262 SILC_GET32_MSB(mask, tmp_mask);
3268 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3269 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3270 /* Cannot operator mode */
3271 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3272 SILC_STATUS_ERR_PERM_DENIED);
3276 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3277 /* Remove the server operator rights */
3278 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3281 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3282 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3283 /* Cannot operator mode */
3284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3285 SILC_STATUS_ERR_PERM_DENIED);
3289 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3290 /* Remove the router operator rights */
3291 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3294 if (mask & SILC_UMODE_GONE) {
3295 client->mode |= SILC_UMODE_GONE;
3297 if (client->mode & SILC_UMODE_GONE)
3298 /* Remove the gone status */
3299 client->mode &= ~SILC_UMODE_GONE;
3302 /* Send UMODE change to primary router */
3303 if (!server->standalone)
3304 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3305 client->id, SILC_ID_CLIENT_LEN,
3308 /* Send command reply to sender */
3309 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3310 SILC_STATUS_OK, ident, 1,
3312 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3313 packet->data, packet->len, FALSE);
3314 silc_buffer_free(packet);
3317 silc_server_command_free(cmd);
3320 /* Checks that client has rights to add or remove channel modes. If any
3321 of the checks fails FALSE is returned. */
3323 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3324 SilcChannelClientEntry client,
3327 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3328 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3330 /* Check whether has rights to change anything */
3331 if (!is_op && !is_fo)
3334 /* Check whether has rights to change everything */
3338 /* We know that client is channel operator, check that they are not
3339 changing anything that requires channel founder rights. Rest of the
3340 modes are available automatically for channel operator. */
3342 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3343 if (is_op && !is_fo)
3346 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3347 if (is_op && !is_fo)
3352 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3353 if (is_op && !is_fo)
3356 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3357 if (is_op && !is_fo)
3362 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3363 if (is_op && !is_fo)
3366 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3367 if (is_op && !is_fo)
3372 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3373 if (is_op && !is_fo)
3376 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3377 if (is_op && !is_fo)
3385 /* Server side command of CMODE. Changes channel mode */
3387 SILC_SERVER_CMD_FUNC(cmode)
3389 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3390 SilcServer server = cmd->server;
3391 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3392 SilcIDListData idata = (SilcIDListData)client;
3393 SilcChannelID *channel_id;
3394 SilcChannelEntry channel;
3395 SilcChannelClientEntry chl;
3396 SilcBuffer packet, cidp;
3397 unsigned char *tmp, *tmp_id, *tmp_mask;
3398 char *cipher = NULL, *hmac = NULL;
3399 unsigned int mode_mask, tmp_len, tmp_len2;
3400 unsigned short ident = silc_command_get_ident(cmd->payload);
3402 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CMODE, cmd, 2, 7);
3404 /* Get Channel ID */
3405 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3408 SILC_STATUS_ERR_NO_CHANNEL_ID);
3411 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3414 SILC_STATUS_ERR_NO_CHANNEL_ID);
3418 /* Get the channel mode mask */
3419 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3422 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3425 SILC_GET32_MSB(mode_mask, tmp_mask);
3427 /* Get channel entry */
3428 channel = silc_idlist_find_channel_by_id(server->local_list,
3431 channel = silc_idlist_find_channel_by_id(server->global_list,
3434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3435 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3440 /* Check whether this client is on the channel */
3441 if (!silc_server_client_on_channel(client, channel)) {
3442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3443 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3447 /* Get entry to the channel user list */
3448 silc_list_start(channel->user_list);
3449 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3450 if (chl->client == client)
3453 /* Check that client has rights to change any requested channel modes */
3454 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3456 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3461 * Check the modes. Modes that requires nothing special operation are
3465 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3466 /* Channel uses private keys to protect traffic. Client(s) has set the
3467 key locally they want to use, server does not know that key. */
3468 /* Nothing interesting to do here */
3470 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3471 /* The mode is removed and we need to generate and distribute
3472 new channel key. Clients are not using private channel keys
3473 anymore after this. */
3475 /* Re-generate channel key */
3476 silc_server_create_channel_key(server, channel, 0);
3478 /* Send the channel key. This sends it to our local clients and if
3479 we are normal server to our router as well. */
3480 silc_server_send_channel_key(server, NULL, channel,
3481 server->server_type == SILC_ROUTER ?
3482 FALSE : !server->standalone);
3484 cipher = channel->channel_key->cipher->name;
3485 hmac = channel->hmac->hmac->name;
3489 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3490 /* User limit is set on channel */
3491 unsigned int user_limit;
3493 /* Get user limit */
3494 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3496 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3497 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3498 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3502 SILC_GET32_MSB(user_limit, tmp);
3503 channel->user_limit = user_limit;
3506 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3507 /* User limit mode is unset. Remove user limit */
3508 channel->user_limit = 0;
3511 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3512 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3513 /* Passphrase has been set to channel */
3515 /* Get the passphrase */
3516 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3518 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3519 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3523 /* Save the passphrase */
3524 channel->passphrase = strdup(tmp);
3527 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3528 /* Passphrase mode is unset. remove the passphrase */
3529 if (channel->passphrase) {
3530 silc_free(channel->passphrase);
3531 channel->passphrase = NULL;
3536 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3537 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3538 /* Cipher to use protect the traffic */
3541 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3543 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3544 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3548 /* Delete old cipher and allocate the new one */
3549 silc_cipher_free(channel->channel_key);
3550 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3552 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3556 /* Re-generate channel key */
3557 silc_server_create_channel_key(server, channel, 0);
3559 /* Send the channel key. This sends it to our local clients and if
3560 we are normal server to our router as well. */
3561 silc_server_send_channel_key(server, NULL, channel,
3562 server->server_type == SILC_ROUTER ?
3563 FALSE : !server->standalone);
3566 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3567 /* Cipher mode is unset. Remove the cipher and revert back to
3569 cipher = channel->cipher;
3571 /* Delete old cipher and allocate default one */
3572 silc_cipher_free(channel->channel_key);
3573 if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc",
3574 &channel->channel_key)) {
3575 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3576 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3580 /* Re-generate channel key */
3581 silc_server_create_channel_key(server, channel, 0);
3583 /* Send the channel key. This sends it to our local clients and if
3584 we are normal server to our router as well. */
3585 silc_server_send_channel_key(server, NULL, channel,
3586 server->server_type == SILC_ROUTER ?
3587 FALSE : !server->standalone);
3591 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3592 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3593 /* HMAC to use protect the traffic */
3594 unsigned char hash[32];
3597 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3600 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3604 /* Delete old hmac and allocate the new one */
3605 silc_hmac_free(channel->hmac);
3606 if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3608 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3612 /* Set the HMAC key out of current channel key. The client must do
3614 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3616 silc_hmac_set_key(channel->hmac, hash,
3617 silc_hash_len(channel->hmac->hash));
3618 memset(hash, 0, sizeof(hash));
3621 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3622 /* Hmac mode is unset. Remove the hmac and revert back to
3624 unsigned char hash[32];
3625 hmac = channel->hmac_name;
3627 /* Delete old hmac and allocate default one */
3628 silc_hmac_free(channel->hmac);
3629 if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL,
3631 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3632 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3636 /* Set the HMAC key out of current channel key. The client must do
3638 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3640 silc_hmac_set_key(channel->hmac, hash,
3641 silc_hash_len(channel->hmac->hash));
3642 memset(hash, 0, sizeof(hash));
3646 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3647 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3648 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3649 /* Set the founder authentication */
3650 SilcAuthPayload auth;
3652 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3654 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3655 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3659 auth = silc_auth_payload_parse(tmp, tmp_len);
3661 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3662 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3666 /* Save the public key */
3667 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3668 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3671 channel->founder_method = silc_auth_get_method(auth);
3673 if (channel->founder_method == SILC_AUTH_PASSWORD) {
3674 tmp = silc_auth_get_data(auth, &tmp_len);
3675 channel->founder_passwd =
3676 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3677 memcpy(channel->founder_passwd, tmp, tmp_len);
3678 channel->founder_passwd_len = tmp_len;
3681 silc_auth_payload_free(auth);
3685 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3686 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3687 if (channel->founder_key)
3688 silc_pkcs_public_key_free(channel->founder_key);
3689 if (channel->founder_passwd) {
3690 silc_free(channel->founder_passwd);
3691 channel->founder_passwd = NULL;
3697 /* Finally, set the mode */
3698 channel->mode = mode_mask;
3700 /* Send CMODE_CHANGE notify */
3701 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3702 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3703 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3704 cidp->data, cidp->len,
3706 cipher, cipher ? strlen(cipher) : 0,
3707 hmac, hmac ? strlen(hmac) : 0);
3709 /* Set CMODE notify type to network */
3710 if (!server->standalone)
3711 silc_server_send_notify_cmode(server, server->router->connection,
3712 server->server_type == SILC_ROUTER ?
3713 TRUE : FALSE, channel,
3714 mode_mask, client->id, SILC_ID_CLIENT,
3718 /* Send command reply to sender */
3719 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3720 SILC_STATUS_OK, ident, 1,
3722 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3723 packet->data, packet->len, FALSE);
3725 silc_buffer_free(packet);
3726 silc_free(channel_id);
3730 silc_server_command_free(cmd);
3733 /* Server side of CUMODE command. Changes client's mode on a channel. */
3735 SILC_SERVER_CMD_FUNC(cumode)
3737 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3738 SilcServer server = cmd->server;
3739 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3740 SilcIDListData idata = (SilcIDListData)client;
3741 SilcChannelID *channel_id;
3742 SilcClientID *client_id;
3743 SilcChannelEntry channel;
3744 SilcClientEntry target_client;
3745 SilcChannelClientEntry chl;
3746 SilcBuffer packet, idp;
3747 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3748 unsigned int target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3750 unsigned short ident = silc_command_get_ident(cmd->payload);
3752 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 4);
3754 /* Get Channel ID */
3755 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3757 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3758 SILC_STATUS_ERR_NO_CHANNEL_ID);
3761 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3764 SILC_STATUS_ERR_NO_CHANNEL_ID);
3768 /* Get channel entry */
3769 channel = silc_idlist_find_channel_by_id(server->local_list,
3772 channel = silc_idlist_find_channel_by_id(server->global_list,
3775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3776 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3781 /* Check whether sender is on the channel */
3782 if (!silc_server_client_on_channel(client, channel)) {
3783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3784 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3788 /* Check that client has rights to change other's rights */
3789 silc_list_start(channel->user_list);
3790 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3791 if (chl->client == client) {
3792 sender_mask = chl->mode;
3797 /* Get the target client's channel mode mask */
3798 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3801 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3804 SILC_GET32_MSB(target_mask, tmp_mask);
3806 /* Get target Client ID */
3807 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3810 SILC_STATUS_ERR_NO_CLIENT_ID);
3813 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3816 SILC_STATUS_ERR_NO_CLIENT_ID);
3820 /* Get target client's entry */
3821 target_client = silc_idlist_find_client_by_id(server->local_list,
3823 if (!target_client) {
3824 target_client = silc_idlist_find_client_by_id(server->global_list,
3828 if (target_client != client &&
3829 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3830 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3831 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3832 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3836 /* Check whether target client is on the channel */
3837 if (target_client != client) {
3838 if (!silc_server_client_on_channel(target_client, channel)) {
3839 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3840 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3844 /* Get entry to the channel user list */
3845 silc_list_start(channel->user_list);
3846 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3847 if (chl->client == target_client)
3855 /* If the target client is founder, no one else can change their mode
3857 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3858 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3859 SILC_STATUS_ERR_NOT_YOU);
3863 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3864 /* The client tries to claim the founder rights. */
3865 unsigned char *tmp_auth;
3866 unsigned int tmp_auth_len, auth_len;
3869 if (target_client != client) {
3870 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3871 SILC_STATUS_ERR_NOT_YOU);
3875 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3876 !channel->founder_key) {
3877 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3878 SILC_STATUS_ERR_NOT_YOU);
3882 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3884 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3885 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3889 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
3890 (void *)channel->founder_passwd : (void *)channel->founder_key);
3891 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3892 channel->founder_passwd_len : 0);
3894 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
3895 channel->founder_method, auth, auth_len,
3896 idata->hash, client->id, SILC_ID_CLIENT)) {
3897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3898 SILC_STATUS_ERR_AUTH_FAILED);
3902 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3905 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3906 if (target_client == client) {
3907 /* Remove channel founder rights from itself */
3908 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3912 SILC_STATUS_ERR_NOT_YOU);
3918 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3919 /* Promote to operator */
3920 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3921 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3922 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3924 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3928 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3932 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3933 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3934 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3935 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3936 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3940 /* Demote to normal user */
3941 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3946 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3947 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3949 /* Send notify to channel, notify only if mode was actually changed. */
3951 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3952 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3953 idp->data, idp->len,
3957 /* Set CUMODE notify type to network */
3958 if (!server->standalone)
3959 silc_server_send_notify_cumode(server, server->router->connection,
3960 server->server_type == SILC_ROUTER ?
3961 TRUE : FALSE, channel,
3962 target_mask, client->id,
3965 SILC_ID_CLIENT_LEN);
3968 /* Send command reply to sender */
3969 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3970 SILC_STATUS_OK, ident, 2,
3972 3, tmp_id, tmp_len);
3973 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3974 packet->data, packet->len, FALSE);
3976 silc_buffer_free(packet);
3977 silc_free(channel_id);
3978 silc_free(client_id);
3979 silc_buffer_free(idp);
3982 silc_server_command_free(cmd);
3985 /* Server side of KICK command. Kicks client out of channel. */
3987 SILC_SERVER_CMD_FUNC(kick)
3989 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3990 SilcServer server = cmd->server;
3991 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3992 SilcClientEntry target_client;
3993 SilcChannelID *channel_id;
3994 SilcClientID *client_id;
3995 SilcChannelEntry channel;
3996 SilcChannelClientEntry chl;
3998 unsigned int tmp_len;
3999 unsigned char *tmp, *comment;
4001 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
4003 /* Get Channel ID */
4004 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4006 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4007 SILC_STATUS_ERR_NO_CHANNEL_ID);
4010 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4013 SILC_STATUS_ERR_NO_CHANNEL_ID);
4017 /* Get channel entry */
4018 channel = silc_idlist_find_channel_by_id(server->local_list,
4021 channel = silc_idlist_find_channel_by_id(server->local_list,
4024 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4025 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4030 /* Check whether sender is on the channel */
4031 if (!silc_server_client_on_channel(client, channel)) {
4032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4033 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4037 /* Check that the kicker is channel operator or channel founder */
4038 silc_list_start(channel->user_list);
4039 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4040 if (chl->client == client) {
4041 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4043 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4050 /* Get target Client ID */
4051 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4053 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4054 SILC_STATUS_ERR_NO_CLIENT_ID);
4057 client_id = silc_id_payload_parse_id(tmp, tmp_len);
4059 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4060 SILC_STATUS_ERR_NO_CLIENT_ID);
4064 /* Get target client's entry */
4065 target_client = silc_idlist_find_client_by_id(server->local_list,
4067 if (!target_client) {
4068 target_client = silc_idlist_find_client_by_id(server->global_list,
4072 /* Check that the target client is not channel founder. Channel founder
4073 cannot be kicked from the channel. */
4074 silc_list_start(channel->user_list);
4075 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4076 if (chl->client == target_client) {
4077 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4079 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4086 /* Check whether target client is on the channel */
4087 if (!silc_server_client_on_channel(target_client, channel)) {
4088 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4089 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4095 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4099 /* Send command reply to sender */
4100 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4103 /* Send KICKED notify to local clients on the channel */
4104 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4105 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4106 SILC_NOTIFY_TYPE_KICKED,
4108 idp->data, idp->len,
4109 comment, comment ? strlen(comment) : 0);
4110 silc_buffer_free(idp);
4112 /* Remove the client from the channel. If the channel does not exist
4113 after removing the client then the client kicked itself off the channel
4114 and we don't have to send anything after that. */
4115 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4116 target_client, FALSE))
4119 /* Send KICKED notify to primary route */
4120 if (!server->standalone)
4121 silc_server_send_notify_kicked(server, server->router->connection,
4122 server->server_type == SILC_ROUTER ?
4123 TRUE : FALSE, channel,
4124 target_client->id, SILC_ID_CLIENT_LEN,
4127 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4128 /* Re-generate channel key */
4129 silc_server_create_channel_key(server, channel, 0);
4131 /* Send the channel key to the channel. The key of course is not sent
4132 to the client who was kicked off the channel. */
4133 silc_server_send_channel_key(server, target_client->connection, channel,
4134 server->server_type == SILC_ROUTER ?
4135 FALSE : !server->standalone);
4139 silc_server_command_free(cmd);
4142 /* Server side of OPER command. Client uses this comand to obtain server
4143 operator privileges to this server/router. */
4145 SILC_SERVER_CMD_FUNC(oper)
4147 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4148 SilcServer server = cmd->server;
4149 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4150 unsigned char *username, *auth;
4151 unsigned int tmp_len;
4152 SilcServerConfigSectionAdminConnection *admin;
4153 SilcIDListData idata = (SilcIDListData)client;
4155 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
4157 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4160 /* Get the username */
4161 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4163 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4164 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4168 /* Get the admin configuration */
4169 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4170 username, client->nickname);
4172 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4173 username, client->nickname);
4175 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4176 SILC_STATUS_ERR_AUTH_FAILED);
4181 /* Get the authentication payload */
4182 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4184 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4185 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4189 /* Verify the authentication data */
4190 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4191 admin->auth_data, admin->auth_data_len,
4192 idata->hash, client->id, SILC_ID_CLIENT)) {
4193 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4194 SILC_STATUS_ERR_AUTH_FAILED);
4198 /* Client is now server operator */
4199 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4201 /* Send UMODE change to primary router */
4202 if (!server->standalone)
4203 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4204 client->id, SILC_ID_CLIENT_LEN,
4207 /* Send reply to the sender */
4208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4212 silc_server_command_free(cmd);
4215 /* Server side of SILCOPER command. Client uses this comand to obtain router
4216 operator privileges to this router. */
4218 SILC_SERVER_CMD_FUNC(silcoper)
4220 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4221 SilcServer server = cmd->server;
4222 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4223 unsigned char *username, *auth;
4224 unsigned int tmp_len;
4225 SilcServerConfigSectionAdminConnection *admin;
4226 SilcIDListData idata = (SilcIDListData)client;
4228 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4230 if (server->server_type == SILC_SERVER)
4233 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4236 /* Get the username */
4237 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4240 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4244 /* Get the admin configuration */
4245 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4246 username, client->nickname);
4248 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4249 username, client->nickname);
4251 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4252 SILC_STATUS_ERR_AUTH_FAILED);
4257 /* Get the authentication payload */
4258 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4260 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4261 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4265 /* Verify the authentication data */
4266 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4267 admin->auth_data, admin->auth_data_len,
4268 idata->hash, client->id, SILC_ID_CLIENT)) {
4269 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4270 SILC_STATUS_ERR_AUTH_FAILED);
4274 /* Client is now router operator */
4275 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4277 /* Send UMODE change to primary router */
4278 if (!server->standalone)
4279 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4280 client->id, SILC_ID_CLIENT_LEN,
4283 /* Send reply to the sender */
4284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4288 silc_server_command_free(cmd);
4291 /* Server side command of CONNECT. Connects us to the specified remote
4292 server or router. */
4294 SILC_SERVER_CMD_FUNC(connect)
4296 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4297 SilcServer server = cmd->server;
4298 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4299 unsigned char *tmp, *host;
4300 unsigned int tmp_len;
4301 unsigned int port = SILC_PORT;
4303 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4305 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4308 /* Check whether client has the permissions. */
4309 if (client->mode == SILC_UMODE_NONE) {
4310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4311 SILC_STATUS_ERR_NO_SERVER_PRIV);
4315 if (server->server_type == SILC_ROUTER &&
4316 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4318 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4322 /* Get the remote server */
4323 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4326 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4331 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4333 SILC_GET32_MSB(port, tmp);
4335 /* Create the connection. It is done with timeout and is async. */
4336 silc_server_create_connection(server, host, port);
4338 /* Send reply to the sender */
4339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4343 silc_server_command_free(cmd);
4346 /* Server side of command BAN. This is used to manage the ban list of the
4347 channel. To add clients and remove clients from the ban list. */
4349 SILC_SERVER_CMD_FUNC(ban)
4351 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4352 SilcServer server = cmd->server;
4353 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4355 SilcChannelEntry channel;
4356 SilcChannelClientEntry chl;
4357 SilcChannelID *channel_id = NULL;
4358 unsigned char *id, *add, *del;
4359 unsigned int id_len, tmp_len;
4360 unsigned short ident = silc_command_get_ident(cmd->payload);
4362 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4365 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4367 /* Get Channel ID */
4368 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4370 channel_id = silc_id_payload_parse_id(id, id_len);
4372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4373 SILC_STATUS_ERR_NO_CHANNEL_ID);
4378 /* Get channel entry. The server must know about the channel since the
4379 client is expected to be on the channel. */
4380 channel = silc_idlist_find_channel_by_id(server->local_list,
4383 channel = silc_idlist_find_channel_by_id(server->global_list,
4386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4387 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4392 /* Check whether this client is on the channel */
4393 if (!silc_server_client_on_channel(client, channel)) {
4394 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4395 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4399 /* Get entry to the channel user list */
4400 silc_list_start(channel->user_list);
4401 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4402 if (chl->client == client)
4405 /* The client must be at least channel operator. */
4406 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4408 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4412 /* Get the new ban and add it to the ban list */
4413 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4415 if (!channel->ban_list)
4416 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4418 channel->ban_list = silc_realloc(channel->ban_list,
4419 sizeof(*channel->ban_list) *
4421 strlen(channel->ban_list) + 2));
4422 if (add[tmp_len - 1] == ',')
4423 add[tmp_len - 1] = '\0';
4425 strncat(channel->ban_list, add, tmp_len);
4426 strncat(channel->ban_list, ",", 1);
4429 /* Get the ban to be removed and remove it from the list */
4430 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4431 if (del && channel->ban_list) {
4432 char *start, *end, *n;
4434 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4435 silc_free(channel->ban_list);
4436 channel->ban_list = NULL;
4438 start = strstr(channel->ban_list, del);
4439 if (start && strlen(start) >= tmp_len) {
4440 end = start + tmp_len;
4441 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4442 strncat(n, channel->ban_list, start - channel->ban_list);
4443 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4445 silc_free(channel->ban_list);
4446 channel->ban_list = n;
4451 /* Send the BAN notify type to our primary router. */
4452 if (!server->standalone && (add || del))
4453 silc_server_send_notify_ban(server, server->router->connection,
4454 server->server_type == SILC_ROUTER ?
4455 TRUE : FALSE, channel, add, del);
4457 /* Send the reply back to the client */
4458 if (channel->ban_list)
4460 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4461 SILC_STATUS_OK, ident, 2,
4463 3, channel->ban_list,
4464 strlen(channel->ban_list) - 1);
4467 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4468 SILC_STATUS_OK, ident, 1,
4471 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4472 packet->data, packet->len, FALSE);
4474 silc_buffer_free(packet);
4478 silc_free(channel_id);
4479 silc_server_command_free(cmd);
4482 /* Server side command of CLOSE. Closes connection to a specified server. */
4484 SILC_SERVER_CMD_FUNC(close)
4486 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4487 SilcServer server = cmd->server;
4488 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4489 SilcServerEntry server_entry;
4490 SilcSocketConnection sock;
4492 unsigned int tmp_len;
4493 unsigned char *name;
4494 unsigned int port = SILC_PORT;
4496 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4498 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4501 /* Check whether client has the permissions. */
4502 if (client->mode == SILC_UMODE_NONE) {
4503 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4504 SILC_STATUS_ERR_NO_SERVER_PRIV);
4508 /* Get the remote server */
4509 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4512 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4517 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4519 SILC_GET32_MSB(port, tmp);
4521 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4523 if (!server_entry) {
4524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4525 SILC_STATUS_ERR_NO_SERVER_ID);
4529 /* Send reply to the sender */
4530 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4533 /* Close the connection to the server */
4534 sock = (SilcSocketConnection)server_entry->connection;
4535 silc_server_free_sock_user_data(server, sock);
4536 silc_server_close_connection(server, sock);
4539 silc_server_command_free(cmd);
4542 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4543 active connections. */
4545 SILC_SERVER_CMD_FUNC(shutdown)
4547 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4548 SilcServer server = cmd->server;
4549 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4551 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4553 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4556 /* Check whether client has the permission. */
4557 if (client->mode == SILC_UMODE_NONE) {
4558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4559 SILC_STATUS_ERR_NO_SERVER_PRIV);
4563 /* Send reply to the sender */
4564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4567 /* Then, gracefully, or not, bring the server down. */
4568 silc_server_stop(server);
4572 silc_server_command_free(cmd);
4575 /* Server side command of LEAVE. Removes client from a channel. */
4577 SILC_SERVER_CMD_FUNC(leave)
4579 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4580 SilcServer server = cmd->server;
4581 SilcSocketConnection sock = cmd->sock;
4582 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4583 SilcChannelID *id = NULL;
4584 SilcChannelEntry channel;
4588 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4590 /* Get Channel ID */
4591 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4593 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4594 SILC_STATUS_ERR_NO_CHANNEL_ID);
4597 id = silc_id_payload_parse_id(tmp, len);
4599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4600 SILC_STATUS_ERR_NO_CHANNEL_ID);
4604 /* Get channel entry */
4605 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4607 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4609 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4610 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4615 /* Check whether this client is on the channel */
4616 if (!silc_server_client_on_channel(id_entry, channel)) {
4617 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4618 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4622 /* Notify routers that they should remove this client from their list
4623 of clients on the channel. Send LEAVE notify type. */
4624 if (!server->standalone)
4625 silc_server_send_notify_leave(server, server->router->connection,
4626 server->server_type == SILC_ROUTER ?
4627 TRUE : FALSE, channel, id_entry->id,
4628 SILC_ID_CLIENT_LEN);
4630 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4633 /* Remove client from channel */
4634 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4636 /* If the channel does not exist anymore we won't send anything */
4639 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4640 /* Re-generate channel key */
4641 silc_server_create_channel_key(server, channel, 0);
4643 /* Send the channel key */
4644 silc_server_send_channel_key(server, NULL, channel,
4645 server->server_type == SILC_ROUTER ?
4646 FALSE : !server->standalone);
4654 silc_server_command_free(cmd);
4657 /* Server side of command USERS. Resolves clients and their USERS currently
4658 joined on the requested channel. The list of Client ID's and their modes
4659 on the channel is sent back. */
4661 SILC_SERVER_CMD_FUNC(users)
4663 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4664 SilcServer server = cmd->server;
4665 SilcChannelEntry channel;
4668 unsigned char *channel_id;
4669 unsigned int channel_id_len;
4670 SilcBuffer client_id_list;
4671 SilcBuffer client_mode_list;
4672 unsigned char lc[4];
4673 unsigned int list_count = 0;
4674 unsigned short ident = silc_command_get_ident(cmd->payload);
4676 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4678 /* Get Channel ID */
4679 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4682 SILC_STATUS_ERR_NO_CHANNEL_ID);
4685 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4688 SILC_STATUS_ERR_NO_CHANNEL_ID);
4692 /* If we are server and we don't know about this channel we will send
4693 the command to our router. If we know about the channel then we also
4694 have the list of users already. */
4695 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4697 if (server->server_type == SILC_SERVER && !server->standalone &&
4701 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4702 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4704 /* Send USERS command */
4705 silc_server_packet_send(server, server->router->connection,
4706 SILC_PACKET_COMMAND, cmd->packet->flags,
4707 tmpbuf->data, tmpbuf->len, TRUE);
4709 /* Reprocess this packet after received reply */
4710 silc_server_command_pending(server, SILC_COMMAND_USERS,
4711 silc_command_get_ident(cmd->payload),
4712 silc_server_command_destructor,
4713 silc_server_command_users,
4714 silc_server_command_dup(cmd));
4715 cmd->pending = TRUE;
4716 silc_command_set_ident(cmd->payload, ident);
4718 silc_buffer_free(tmpbuf);
4723 /* We are router and we will check the global list as well. */
4724 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4726 /* Channel really does not exist */
4727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4728 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4733 /* Get the users list */
4734 silc_server_get_users_on_channel(server, channel, &client_id_list,
4735 &client_mode_list, &list_count);
4738 SILC_PUT32_MSB(list_count, lc);
4741 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4742 SILC_STATUS_OK, ident, 4,
4743 2, channel_id, channel_id_len,
4745 4, client_id_list->data,
4746 client_id_list->len,
4747 5, client_mode_list->data,
4748 client_mode_list->len);
4749 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4750 packet->data, packet->len, FALSE);
4752 silc_buffer_free(packet);
4753 silc_buffer_free(client_id_list);
4754 silc_buffer_free(client_mode_list);
4758 silc_server_command_free(cmd);