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 void silc_server_command_send_users(SilcServer server,
41 SilcSocketConnection sock,
42 SilcChannelEntry channel,
45 /* Server command list. */
46 SilcServerCommand silc_command_list[] =
48 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
49 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
54 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(connect, CONNECT,
59 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
60 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
62 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(restart, RESTART,
69 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
70 SILC_SERVER_CMD(close, CLOSE,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72 SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
73 SILC_SERVER_CMD(silcoper, SILCOPER,
74 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
75 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
76 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
81 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
83 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
85 SILC_LOG_DEBUG(("Start")); \
88 silc_server_command_send_status_reply(cmd, command, \
89 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
90 silc_server_command_free(cmd); \
94 silc_server_command_send_status_reply(cmd, command, \
95 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
96 silc_server_command_free(cmd); \
101 /* Returns TRUE if the connection is registered. Unregistered connections
102 usually cannot send commands hence the check. */
104 static int silc_server_is_registered(SilcServer server,
105 SilcSocketConnection sock,
106 SilcServerCommandContext cmd,
109 SilcIDListData idata = (SilcIDListData)sock->user_data;
110 if (idata->registered)
113 silc_server_command_send_status_reply(cmd, command,
114 SILC_STATUS_ERR_NOT_REGISTERED);
115 silc_server_command_free(cmd);
119 /* Processes received command packet. */
121 void silc_server_command_process(SilcServer server,
122 SilcSocketConnection sock,
123 SilcPacketContext *packet)
125 SilcServerCommandContext ctx;
126 SilcServerCommand *cmd;
129 /* XXX allow commands in but do not execute them more than once per
132 /* Check whether it is allowed for this connection to execute any
134 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
136 SilcClientEntry client = (SilcClientEntry)sock->user_data;
141 /* Allow only one command executed in 2 seconds. */
142 curtime = time(NULL);
143 if (client->last_command && (curtime - client->last_command) < 2)
146 /* Update access time */
147 client->last_command = curtime;
151 /* Allocate command context. This must be free'd by the
152 command routine receiving it. */
153 ctx = silc_server_command_alloc();
154 ctx->server = server;
155 ctx->sock = silc_socket_dup(sock);
156 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
158 /* Parse the command payload in the packet */
159 ctx->payload = silc_command_payload_parse(packet->buffer);
161 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
162 silc_buffer_free(packet->buffer);
163 silc_packet_context_free(packet);
164 silc_socket_free(ctx->sock);
168 ctx->args = silc_command_get_args(ctx->payload);
170 /* Execute command. If this fails the packet is dropped. */
171 for (cmd = silc_command_list; cmd->cb; cmd++)
172 if (cmd->cmd == silc_command_get(ctx->payload)) {
174 if (!(cmd->flags & SILC_CF_REG)) {
179 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
186 SILC_LOG_ERROR(("Unknown command, packet dropped"));
187 silc_server_command_free(ctx);
192 /* Allocate Command Context */
194 SilcServerCommandContext silc_server_command_alloc()
196 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
201 /* Free's the command context allocated before executing the command */
203 void silc_server_command_free(SilcServerCommandContext ctx)
206 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
208 if (ctx->users < 1) {
210 silc_command_free_payload(ctx->payload);
212 silc_packet_context_free(ctx->packet);
214 silc_socket_free(ctx->sock); /* Decrease reference counter */
219 /* Duplicate Command Context by adding reference counter. The context won't
220 be free'd untill it hits zero. */
222 SilcServerCommandContext
223 silc_server_command_dup(SilcServerCommandContext ctx)
226 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
231 /* Add new pending command to be executed when reply to a command has been
232 received. The `reply_cmd' is the command that will call the `callback'
233 with `context' when reply has been received. If `ident' is non-zero
234 the `callback' will be executed when received reply with command
235 identifier `ident'. */
237 void silc_server_command_pending(SilcServer server,
238 SilcCommand reply_cmd,
239 unsigned short ident,
240 SilcServerPendingDestructor destructor,
241 SilcCommandCb callback,
244 SilcServerCommandPending *reply;
246 reply = silc_calloc(1, sizeof(*reply));
247 reply->reply_cmd = reply_cmd;
248 reply->ident = ident;
249 reply->context = context;
250 reply->callback = callback;
251 reply->destructor = destructor;
252 silc_dlist_add(server->pending_commands, reply);
255 /* Deletes pending command by reply command type. */
257 void silc_server_command_pending_del(SilcServer server,
258 SilcCommand reply_cmd,
259 unsigned short ident)
261 SilcServerCommandPending *r;
263 silc_dlist_start(server->pending_commands);
264 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
265 if (r->reply_cmd == reply_cmd && r->ident == ident) {
266 silc_dlist_del(server->pending_commands, r);
272 /* Checks for pending commands and marks callbacks to be called from
273 the command reply function. Returns TRUE if there were pending command. */
275 int silc_server_command_pending_check(SilcServer server,
276 SilcServerCommandReplyContext ctx,
278 unsigned short ident)
280 SilcServerCommandPending *r;
282 silc_dlist_start(server->pending_commands);
283 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
284 if (r->reply_cmd == command && r->ident == ident) {
285 ctx->context = r->context;
286 ctx->callback = r->callback;
287 ctx->destructor = r->destructor;
296 /* Destructor function for pending callbacks. This is called when using
297 pending commands to free the context given for the pending command. */
299 static void silc_server_command_destructor(void *context)
301 silc_server_command_free((SilcServerCommandContext)context);
304 /* Sends simple status message as command reply packet */
307 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
309 SilcCommandStatus status)
313 SILC_LOG_DEBUG(("Sending command status %d", status));
315 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
316 silc_server_packet_send(cmd->server, cmd->sock,
317 SILC_PACKET_COMMAND_REPLY, 0,
318 buffer->data, buffer->len, FALSE);
319 silc_buffer_free(buffer);
322 /* Sends command status reply with one extra argument. The argument
323 type must be sent as argument. */
326 silc_server_command_send_status_data(SilcServerCommandContext cmd,
328 SilcCommandStatus status,
329 unsigned int arg_type,
331 unsigned int arg_len)
335 SILC_LOG_DEBUG(("Sending command status %d", status));
337 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
338 arg_type, arg, arg_len);
339 silc_server_packet_send(cmd->server, cmd->sock,
340 SILC_PACKET_COMMAND_REPLY, 0,
341 buffer->data, buffer->len, FALSE);
342 silc_buffer_free(buffer);
345 /******************************************************************************
349 ******************************************************************************/
352 silc_server_command_whois_parse(SilcServerCommandContext cmd,
353 SilcClientID ***client_id,
354 unsigned int *client_id_count,
362 unsigned int argc = silc_argument_get_arg_num(cmd->args);
365 /* If client ID is in the command it must be used instead of nickname */
366 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
368 /* No ID, get the nickname@server string and parse it. */
369 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
371 if (strchr(tmp, '@')) {
372 len = strcspn(tmp, "@");
373 *nickname = silc_calloc(len + 1, sizeof(char));
374 memcpy(*nickname, tmp, len);
375 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
376 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
378 *nickname = strdup(tmp);
381 silc_server_command_send_status_reply(cmd, command,
382 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
386 /* Command includes ID, we must use that. Also check whether the command
387 has more than one ID set - take them all. */
389 *client_id = silc_calloc(1, sizeof(**client_id));
390 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
391 if ((*client_id)[0] == NULL) {
392 silc_free(*client_id);
395 *client_id_count = 1;
397 /* Take all ID's from the command packet */
399 for (k = 1, i = 4; i < argc + 1; i++) {
400 tmp = silc_argument_get_arg_type(cmd->args, i, &len);
402 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
403 (*client_id_count + 1));
404 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
405 if ((*client_id)[k] == NULL) {
406 /* Cleanup all and fail */
407 for (i = 0; i < *client_id_count; i++)
408 silc_free((*client_id)[i]);
409 silc_free(*client_id);
412 (*client_id_count)++;
418 /* Command includes ID, use that */
421 /* Get the max count of reply messages allowed */
422 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
432 silc_server_command_whois_check(SilcServerCommandContext cmd,
433 SilcClientEntry *clients,
434 unsigned int clients_count)
436 SilcServer server = cmd->server;
438 SilcClientEntry entry;
440 for (i = 0; i < clients_count; i++) {
443 if (!entry->nickname || !entry->username) {
445 unsigned short old_ident;
450 old_ident = silc_command_get_ident(cmd->payload);
451 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
452 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
454 /* Send WHOIS command */
455 silc_server_packet_send(server, entry->router->connection,
456 SILC_PACKET_COMMAND, cmd->packet->flags,
457 tmpbuf->data, tmpbuf->len, TRUE);
459 /* Reprocess this packet after received reply */
460 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
461 silc_command_get_ident(cmd->payload),
462 silc_server_command_destructor,
463 silc_server_command_whois,
464 silc_server_command_dup(cmd));
467 silc_command_set_ident(cmd->payload, old_ident);
469 silc_buffer_free(tmpbuf);
478 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
479 SilcClientEntry *clients,
480 unsigned int clients_count)
482 SilcServer server = cmd->server;
484 int i, count = 0, len;
485 SilcBuffer packet, idp;
486 SilcClientEntry entry;
487 SilcCommandStatus status;
488 unsigned short ident = silc_command_get_ident(cmd->payload);
490 status = SILC_STATUS_OK;
491 if (clients_count > 1)
492 status = SILC_STATUS_LIST_START;
494 for (i = 0; i < clients_count; i++) {
497 if (count && i - 1 == count)
500 if (clients_count > 2)
501 status = SILC_STATUS_LIST_ITEM;
503 if (clients_count > 1 && i == clients_count - 1)
504 status = SILC_STATUS_LIST_END;
506 /* Sanity check, however these should never fail. However, as
507 this sanity check has been added here they have failed. */
508 if (!entry->nickname || !entry->username)
511 /* Send WHOIS reply */
512 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
513 tmp = silc_argument_get_first_arg(cmd->args, NULL);
517 char nh[256], uh[256];
518 unsigned char idle[4];
519 SilcSocketConnection hsock;
521 memset(uh, 0, sizeof(uh));
522 memset(nh, 0, sizeof(nh));
524 strncat(nh, entry->nickname, strlen(entry->nickname));
525 if (!strchr(entry->nickname, '@')) {
527 len = entry->router ? strlen(entry->router->server_name) :
528 strlen(server->server_name);
529 strncat(nh, entry->router ? entry->router->server_name :
530 server->server_name, len);
533 strncat(uh, entry->username, strlen(entry->username));
534 if (!strchr(entry->username, '@')) {
536 hsock = (SilcSocketConnection)entry->connection;
537 len = strlen(hsock->hostname);
538 strncat(uh, hsock->hostname, len);
541 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
546 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
548 2, idp->data, idp->len,
552 strlen(entry->userinfo),
556 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
558 2, idp->data, idp->len,
564 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
565 0, packet->data, packet->len, FALSE);
567 silc_buffer_free(packet);
568 silc_buffer_free(idp);
573 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
575 SilcServer server = cmd->server;
576 char *nick = NULL, *server_name = NULL;
577 int count = 0, clients_count = 0;
578 SilcClientEntry *clients = NULL, entry;
579 SilcClientID **client_id = NULL;
580 unsigned int client_id_count = 0;
583 /* Protocol dictates that we must always send the received WHOIS request
584 to our router if we are normal server, so let's do it now unless we
585 are standalone. We will not send any replies to the client until we
586 have received reply from the router. */
587 if (server->server_type == SILC_SERVER &&
588 !cmd->pending && !server->standalone) {
590 unsigned short old_ident;
592 old_ident = silc_command_get_ident(cmd->payload);
593 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
594 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
596 /* Send WHOIS command to our router */
597 silc_server_packet_send(server, (SilcSocketConnection)
598 server->router->connection,
599 SILC_PACKET_COMMAND, cmd->packet->flags,
600 tmpbuf->data, tmpbuf->len, TRUE);
602 /* Reprocess this packet after received reply from router */
603 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
604 silc_command_get_ident(cmd->payload),
605 silc_server_command_destructor,
606 silc_server_command_whois,
607 silc_server_command_dup(cmd));
610 silc_command_set_ident(cmd->payload, old_ident);
612 silc_buffer_free(tmpbuf);
617 /* We are ready to process the command request. Let's search for the
618 requested client and send reply to the requesting client. */
620 /* Parse the whois request */
621 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
622 &nick, &server_name, &count,
626 /* Get all clients matching that ID or nickname from local list */
627 if (client_id_count) {
628 /* Check all Client ID's received in the command packet */
629 for (i = 0; i < client_id_count; i++) {
630 entry = silc_idlist_find_client_by_id(server->local_list,
633 clients = silc_realloc(clients, sizeof(*clients) *
634 (clients_count + 1));
635 clients[clients_count++] = entry;
639 clients = silc_idlist_get_clients_by_nickname(server->local_list,
644 /* Check global list as well */
646 if (client_id_count) {
647 /* Check all Client ID's received in the command packet */
648 for (i = 0; i < client_id_count; i++) {
649 entry = silc_idlist_find_client_by_id(server->global_list,
652 clients = silc_realloc(clients, sizeof(*clients) *
653 (clients_count + 1));
654 clients[clients_count++] = entry;
658 clients = silc_idlist_get_clients_by_nickname(server->global_list,
665 /* Such client(s) really does not exist in the SILC network. */
666 if (!client_id_count) {
667 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
668 SILC_STATUS_ERR_NO_SUCH_NICK,
669 3, nick, strlen(nick));
671 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
672 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
673 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
674 2, idp->data, idp->len);
675 silc_buffer_free(idp);
680 /* Router always finds the client entry if it exists in the SILC network.
681 However, it might be incomplete entry and does not include all the
682 mandatory fields that WHOIS command reply requires. Check for these and
683 make query from the server who owns the client if some fields are
685 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
690 /* Send the command reply to the client */
691 silc_server_command_whois_send_reply(cmd, clients, clients_count);
694 if (client_id_count) {
695 for (i = 0; i < client_id_count; i++)
696 silc_free(client_id[i]);
697 silc_free(client_id);
704 silc_free(server_name);
710 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
712 SilcServer server = cmd->server;
713 char *nick = NULL, *server_name = NULL;
714 int count = 0, clients_count = 0;
715 SilcClientEntry *clients = NULL, entry;
716 SilcClientID **client_id = NULL;
717 unsigned int client_id_count = 0;
720 /* Parse the whois request */
721 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
722 &nick, &server_name, &count,
726 /* Process the command request. Let's search for the requested client and
727 send reply to the requesting server. */
729 if (client_id_count) {
730 /* Check all Client ID's received in the command packet */
731 for (i = 0; i < client_id_count; i++) {
732 entry = silc_idlist_find_client_by_id(server->local_list,
735 clients = silc_realloc(clients, sizeof(*clients) *
736 (clients_count + 1));
737 clients[clients_count++] = entry;
741 clients = silc_idlist_get_clients_by_nickname(server->local_list,
745 clients = silc_idlist_get_clients_by_hash(server->local_list,
746 nick, server->md5hash,
750 /* If we are router we will check our global list as well. */
751 if (!clients && server->server_type == SILC_ROUTER) {
752 if (client_id_count) {
753 /* Check all Client ID's received in the command packet */
754 for (i = 0; i < client_id_count; i++) {
755 entry = silc_idlist_find_client_by_id(server->global_list,
758 clients = silc_realloc(clients, sizeof(*clients) *
759 (clients_count + 1));
760 clients[clients_count++] = entry;
764 clients = silc_idlist_get_clients_by_nickname(server->global_list,
768 clients = silc_idlist_get_clients_by_hash(server->global_list,
769 nick, server->md5hash,
775 /* Such a client really does not exist in the SILC network. */
776 if (!client_id_count) {
777 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
778 SILC_STATUS_ERR_NO_SUCH_NICK,
779 3, nick, strlen(nick));
781 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
782 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
783 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
784 2, idp->data, idp->len);
785 silc_buffer_free(idp);
790 /* Router always finds the client entry if it exists in the SILC network.
791 However, it might be incomplete entry and does not include all the
792 mandatory fields that WHOIS command reply requires. Check for these and
793 make query from the server who owns the client if some fields are
795 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
800 /* Send the command reply to the client */
801 silc_server_command_whois_send_reply(cmd, clients, clients_count);
804 if (client_id_count) {
805 for (i = 0; i < client_id_count; i++)
806 silc_free(client_id[i]);
807 silc_free(client_id);
814 silc_free(server_name);
819 /* Server side of command WHOIS. Processes user's query and sends found
820 results as command replies back to the client. */
822 SILC_SERVER_CMD_FUNC(whois)
824 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
827 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
829 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
830 ret = silc_server_command_whois_from_client(cmd);
831 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
832 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
833 ret = silc_server_command_whois_from_server(cmd);
836 silc_server_command_free(cmd);
839 SILC_SERVER_CMD_FUNC(whowas)
843 /******************************************************************************
847 ******************************************************************************/
849 /* Checks that all mandatory fields are present. If not then send WHOIS
850 request to the server who owns the client. We use WHOIS because we want
851 to get as much information as possible at once. */
854 silc_server_command_identify_check(SilcServerCommandContext cmd,
855 SilcClientEntry *clients,
856 unsigned int clients_count)
858 SilcServer server = cmd->server;
860 SilcClientEntry entry;
862 for (i = 0; i < clients_count; i++) {
865 if (!entry->nickname) {
867 unsigned short old_ident;
872 old_ident = silc_command_get_ident(cmd->payload);
873 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
874 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
875 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
877 /* Send WHOIS request. We send WHOIS since we're doing the requesting
878 now anyway so make it a good one. */
879 silc_server_packet_send(server, entry->router->connection,
880 SILC_PACKET_COMMAND, cmd->packet->flags,
881 tmpbuf->data, tmpbuf->len, TRUE);
883 /* Reprocess this packet after received reply */
884 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
885 silc_command_get_ident(cmd->payload),
886 silc_server_command_destructor,
887 silc_server_command_identify,
888 silc_server_command_dup(cmd));
892 /* Put old data back to the Command Payload we just changed */
893 silc_command_set_ident(cmd->payload, old_ident);
894 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
896 silc_buffer_free(tmpbuf);
905 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
906 SilcClientEntry *clients,
907 unsigned int clients_count)
909 SilcServer server = cmd->server;
911 int i, count = 0, len;
912 SilcBuffer packet, idp;
913 SilcClientEntry entry;
914 SilcCommandStatus status;
915 unsigned short ident = silc_command_get_ident(cmd->payload);
917 status = SILC_STATUS_OK;
918 if (clients_count > 1)
919 status = SILC_STATUS_LIST_START;
921 for (i = 0; i < clients_count; i++) {
924 if (count && i - 1 == count)
927 if (clients_count > 2)
928 status = SILC_STATUS_LIST_ITEM;
930 if (clients_count > 1 && i == clients_count - 1)
931 status = SILC_STATUS_LIST_END;
933 /* Send IDENTIFY reply */
934 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
935 tmp = silc_argument_get_first_arg(cmd->args, NULL);
939 char nh[256], uh[256];
940 SilcSocketConnection hsock;
942 memset(uh, 0, sizeof(uh));
943 memset(nh, 0, sizeof(nh));
945 strncat(nh, entry->nickname, strlen(entry->nickname));
946 if (!strchr(entry->nickname, '@')) {
948 len = entry->router ? strlen(entry->router->server_name) :
949 strlen(server->server_name);
950 strncat(nh, entry->router ? entry->router->server_name :
951 server->server_name, len);
954 if (!entry->username) {
955 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
956 SILC_STATUS_OK, ident, 2,
957 2, idp->data, idp->len,
960 strncat(uh, entry->username, strlen(entry->username));
961 if (!strchr(entry->username, '@')) {
963 hsock = (SilcSocketConnection)entry->connection;
964 len = strlen(hsock->hostname);
965 strncat(uh, hsock->hostname, len);
968 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
969 SILC_STATUS_OK, ident, 3,
970 2, idp->data, idp->len,
975 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
976 0, packet->data, packet->len, FALSE);
978 silc_buffer_free(packet);
979 silc_buffer_free(idp);
985 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
987 SilcServer server = cmd->server;
988 char *nick = NULL, *server_name = NULL;
989 int count = 0, clients_count = 0;
990 SilcClientEntry *clients = NULL, entry;
991 SilcClientID **client_id = NULL;
992 unsigned int client_id_count = 0;
995 /* Protocol dictates that we must always send the received IDENTIFY request
996 to our router if we are normal server, so let's do it now unless we
997 are standalone. We will not send any replies to the client until we
998 have received reply from the router. */
999 if (server->server_type == SILC_SERVER &&
1000 !cmd->pending && !server->standalone) {
1002 unsigned short old_ident;
1004 old_ident = silc_command_get_ident(cmd->payload);
1005 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1006 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1008 /* Send IDENTIFY command to our router */
1009 silc_server_packet_send(server, (SilcSocketConnection)
1010 server->router->connection,
1011 SILC_PACKET_COMMAND, cmd->packet->flags,
1012 tmpbuf->data, tmpbuf->len, TRUE);
1014 /* Reprocess this packet after received reply from router */
1015 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1016 silc_command_get_ident(cmd->payload),
1017 silc_server_command_destructor,
1018 silc_server_command_identify,
1019 silc_server_command_dup(cmd));
1020 cmd->pending = TRUE;
1022 silc_command_set_ident(cmd->payload, old_ident);
1024 silc_buffer_free(tmpbuf);
1029 /* We are ready to process the command request. Let's search for the
1030 requested client and send reply to the requesting client. */
1032 /* Parse the IDENTIFY request */
1033 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1034 &nick, &server_name, &count,
1035 SILC_COMMAND_IDENTIFY))
1038 /* Get all clients matching that ID or nickname from local list */
1039 if (client_id_count) {
1040 /* Check all Client ID's received in the command packet */
1041 for (i = 0; i < client_id_count; i++) {
1042 entry = silc_idlist_find_client_by_id(server->local_list,
1043 client_id[i], NULL);
1045 clients = silc_realloc(clients, sizeof(*clients) *
1046 (clients_count + 1));
1047 clients[clients_count++] = entry;
1051 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1056 /* Check global list as well */
1058 if (client_id_count) {
1059 /* Check all Client ID's received in the command packet */
1060 for (i = 0; i < client_id_count; i++) {
1061 entry = silc_idlist_find_client_by_id(server->global_list,
1062 client_id[i], NULL);
1064 clients = silc_realloc(clients, sizeof(*clients) *
1065 (clients_count + 1));
1066 clients[clients_count++] = entry;
1070 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1077 /* Such a client really does not exist in the SILC network. */
1078 if (!client_id_count) {
1079 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1080 SILC_STATUS_ERR_NO_SUCH_NICK,
1081 3, nick, strlen(nick));
1083 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1084 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1085 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1086 2, idp->data, idp->len);
1087 silc_buffer_free(idp);
1092 /* Check that all mandatory fields are present and request those data
1093 from the server who owns the client if necessary. */
1094 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1099 /* Send the command reply to the client */
1100 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1103 if (client_id_count) {
1104 for (i = 0; i < client_id_count; i++)
1105 silc_free(client_id[i]);
1106 silc_free(client_id);
1113 silc_free(server_name);
1119 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1121 SilcServer server = cmd->server;
1122 char *nick = NULL, *server_name = NULL;
1123 int count = 0, clients_count = 0;
1124 SilcClientEntry *clients = NULL, entry;
1125 SilcClientID **client_id = NULL;
1126 unsigned int client_id_count = 0;
1129 /* Parse the IDENTIFY request */
1130 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1131 &nick, &server_name, &count,
1132 SILC_COMMAND_IDENTIFY))
1135 /* Process the command request. Let's search for the requested client and
1136 send reply to the requesting server. */
1138 if (client_id_count) {
1139 /* Check all Client ID's received in the command packet */
1140 for (i = 0; i < client_id_count; i++) {
1141 entry = silc_idlist_find_client_by_id(server->local_list,
1142 client_id[i], NULL);
1144 clients = silc_realloc(clients, sizeof(*clients) *
1145 (clients_count + 1));
1146 clients[clients_count++] = entry;
1150 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1154 clients = silc_idlist_get_clients_by_hash(server->local_list,
1155 nick, server->md5hash,
1159 /* If we are router we will check our global list as well. */
1160 if (!clients && server->server_type == SILC_ROUTER) {
1161 if (client_id_count) {
1162 /* Check all Client ID's received in the command packet */
1163 for (i = 0; i < client_id_count; i++) {
1164 entry = silc_idlist_find_client_by_id(server->global_list,
1165 client_id[i], NULL);
1167 clients = silc_realloc(clients, sizeof(*clients) *
1168 (clients_count + 1));
1169 clients[clients_count++] = entry;
1173 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1177 clients = silc_idlist_get_clients_by_hash(server->global_list,
1178 nick, server->md5hash,
1184 /* Such a client really does not exist in the SILC network. */
1185 if (!client_id_count) {
1186 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1187 SILC_STATUS_ERR_NO_SUCH_NICK,
1188 3, nick, strlen(nick));
1190 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1191 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1192 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1193 2, idp->data, idp->len);
1194 silc_buffer_free(idp);
1199 /* Check that all mandatory fields are present and request those data
1200 from the server who owns the client if necessary. */
1201 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1206 /* Send the command reply */
1207 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1210 if (client_id_count) {
1211 for (i = 0; i < client_id_count; i++)
1212 silc_free(client_id[i]);
1213 silc_free(client_id);
1220 silc_free(server_name);
1225 SILC_SERVER_CMD_FUNC(identify)
1227 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1230 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1232 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1233 ret = silc_server_command_identify_from_client(cmd);
1234 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1235 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1236 ret = silc_server_command_identify_from_server(cmd);
1239 silc_server_command_free(cmd);
1242 /* Checks string for bad characters and returns TRUE if they are found. */
1244 static int silc_server_command_bad_chars(char *nick)
1246 if (strchr(nick, '\\')) return TRUE;
1247 if (strchr(nick, '\"')) return TRUE;
1248 if (strchr(nick, '´')) return TRUE;
1249 if (strchr(nick, '`')) return TRUE;
1250 if (strchr(nick, '\'')) return TRUE;
1251 if (strchr(nick, '*')) return TRUE;
1252 if (strchr(nick, '/')) return TRUE;
1253 if (strchr(nick, '@')) return TRUE;
1258 /* Server side of command NICK. Sets nickname for user. Setting
1259 nickname causes generation of a new client ID for the client. The
1260 new client ID is sent to the client after changing the nickname. */
1262 SILC_SERVER_CMD_FUNC(nick)
1264 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1265 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1266 SilcServer server = cmd->server;
1267 SilcBuffer packet, nidp, oidp;
1268 SilcClientID *new_id;
1271 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1273 /* Check nickname */
1274 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1275 if (silc_server_command_bad_chars(nick) == TRUE) {
1276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1277 SILC_STATUS_ERR_BAD_NICKNAME);
1281 /* Create new Client ID */
1282 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1283 cmd->server->md5hash, nick,
1286 /* Send notify about nickname change to our router. We send the new
1287 ID and ask to replace it with the old one. If we are router the
1288 packet is broadcasted. Send NICK_CHANGE notify. */
1289 if (!server->standalone)
1290 silc_server_send_notify_nick_change(server, server->router->connection,
1291 server->server_type == SILC_SERVER ?
1292 FALSE : TRUE, client->id,
1293 new_id, SILC_ID_CLIENT_LEN);
1295 /* Remove old cache entry */
1296 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1299 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1303 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1304 silc_free(client->id);
1307 /* Save the nickname as this client is our local client */
1308 if (client->nickname)
1309 silc_free(client->nickname);
1311 client->nickname = strdup(nick);
1312 client->id = new_id;
1314 /* Update client cache */
1315 silc_idcache_add(server->local_list->clients, client->nickname,
1316 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1318 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1320 /* Send NICK_CHANGE notify to the client's channels */
1321 silc_server_send_notify_on_channels(server, client,
1322 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1323 oidp->data, oidp->len,
1324 nidp->data, nidp->len);
1326 /* Send the new Client ID as reply command back to client */
1327 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1328 SILC_STATUS_OK, 0, 1,
1329 2, nidp->data, nidp->len);
1330 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1331 0, packet->data, packet->len, FALSE);
1333 silc_buffer_free(packet);
1334 silc_buffer_free(nidp);
1335 silc_buffer_free(oidp);
1338 silc_server_command_free(cmd);
1341 SILC_SERVER_CMD_FUNC(list)
1345 /* Server side of TOPIC command. Sets topic for channel and/or returns
1346 current topic to client. */
1348 SILC_SERVER_CMD_FUNC(topic)
1350 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1351 SilcServer server = cmd->server;
1352 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1353 SilcChannelID *channel_id;
1354 SilcChannelEntry channel;
1355 SilcChannelClientEntry chl;
1356 SilcBuffer packet, idp;
1358 unsigned int argc, tmp_len;
1360 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1362 argc = silc_argument_get_arg_num(cmd->args);
1364 /* Get Channel ID */
1365 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1367 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1368 SILC_STATUS_ERR_NO_CHANNEL_ID);
1371 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1374 SILC_STATUS_ERR_NO_CHANNEL_ID);
1378 /* Check whether the channel exists */
1379 channel = silc_idlist_find_channel_by_id(server->local_list,
1382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1383 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1389 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1391 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1392 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1396 if (strlen(tmp) > 256) {
1397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1398 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1402 /* See whether has rights to change topic */
1403 silc_list_start(channel->user_list);
1404 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1405 if (chl->client == client)
1408 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1409 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1411 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1416 /* Set the topic for channel */
1418 silc_free(channel->topic);
1419 channel->topic = strdup(tmp);
1421 /* Send TOPIC_SET notify type to the network */
1422 if (!server->standalone)
1423 silc_server_send_notify_topic_set(server, server->router->connection,
1424 server->server_type == SILC_ROUTER ?
1425 TRUE : FALSE, channel, client->id,
1426 SILC_ID_CLIENT_LEN, channel->topic);
1428 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1430 /* Send notify about topic change to all clients on the channel */
1431 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1432 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1433 idp->data, idp->len,
1434 channel->topic, strlen(channel->topic));
1435 silc_buffer_free(idp);
1438 /* Send the topic to client as reply packet */
1439 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1441 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1442 SILC_STATUS_OK, 0, 2,
1443 2, idp->data, idp->len,
1445 strlen(channel->topic));
1447 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1448 SILC_STATUS_OK, 0, 1,
1449 2, idp->data, idp->len);
1450 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1451 0, packet->data, packet->len, FALSE);
1453 silc_buffer_free(packet);
1454 silc_buffer_free(idp);
1455 silc_free(channel_id);
1458 silc_server_command_free(cmd);
1461 /* Server side of INVITE command. Invites some client to join some channel. */
1463 SILC_SERVER_CMD_FUNC(invite)
1465 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1466 SilcServer server = cmd->server;
1467 SilcSocketConnection sock = cmd->sock, dest_sock;
1468 SilcClientEntry sender, dest;
1469 SilcClientID *dest_id;
1470 SilcChannelEntry channel;
1471 SilcChannelID *channel_id;
1476 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1478 /* Get destination ID */
1479 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1481 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1482 SILC_STATUS_ERR_NO_CLIENT_ID);
1485 dest_id = silc_id_payload_parse_id(tmp, len);
1487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1488 SILC_STATUS_ERR_NO_CLIENT_ID);
1492 /* Get Channel ID */
1493 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1496 SILC_STATUS_ERR_NO_CHANNEL_ID);
1499 channel_id = silc_id_payload_parse_id(tmp, len);
1501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1502 SILC_STATUS_ERR_NO_CHANNEL_ID);
1506 /* Check whether the channel exists */
1507 channel = silc_idlist_find_channel_by_id(server->local_list,
1510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1511 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1515 /* Check whether the sender of this command is on the channel. */
1516 sender = (SilcClientEntry)sock->user_data;
1517 if (!silc_server_client_on_channel(sender, channel)) {
1518 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1519 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1523 /* Check whether the channel is invite-only channel. If yes then the
1524 sender of this command must be at least channel operator. */
1525 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1526 SilcChannelClientEntry chl;
1528 silc_list_start(channel->user_list);
1529 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1530 if (chl->client == sender) {
1531 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1533 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1540 /* Find the connection data for the destination. If it is local we will
1541 send it directly otherwise we will send it to router for routing. */
1542 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1544 dest_sock = (SilcSocketConnection)dest->connection;
1546 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1548 /* Check whether the requested client is already on the channel. */
1549 /* XXX if we are normal server we don't know about global clients on
1550 the channel thus we must request it (USERS command), check from
1551 local cache as well. */
1552 if (silc_server_client_on_channel(dest, channel)) {
1553 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1554 SILC_STATUS_ERR_USER_ON_CHANNEL);
1558 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1560 /* Send notify to the client that is invited to the channel */
1561 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1563 SILC_NOTIFY_TYPE_INVITE, 2,
1564 sidp->data, sidp->len, tmp, len);
1566 /* Send command reply */
1567 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1570 silc_buffer_free(sidp);
1573 silc_server_command_free(cmd);
1576 /* Quits connection to client. This gets called if client won't
1577 close the connection even when it has issued QUIT command. */
1579 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1581 SilcServer server = (SilcServer)context;
1582 SilcSocketConnection sock = server->sockets[fd];
1584 /* Free all client specific data, such as client entry and entires
1585 on channels this client may be on. */
1586 silc_server_free_sock_user_data(server, sock);
1588 /* Close the connection on our side */
1589 silc_server_close_connection(server, sock);
1592 /* Quits SILC session. This is the normal way to disconnect client. */
1594 SILC_SERVER_CMD_FUNC(quit)
1596 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1597 SilcServer server = cmd->server;
1598 SilcSocketConnection sock = cmd->sock;
1600 SILC_LOG_DEBUG(("Start"));
1602 /* We quit the connection with little timeout */
1603 silc_task_register(server->timeout_queue, sock->sock,
1604 silc_server_command_quit_cb, server,
1605 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1607 silc_server_command_free(cmd);
1610 SILC_SERVER_CMD_FUNC(kill)
1614 /* Server side of command INFO. This sends information about us to
1615 the client. If client requested specific server we will send the
1616 command to that server. */
1618 SILC_SERVER_CMD_FUNC(info)
1620 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1621 SilcServer server = cmd->server;
1622 SilcBuffer packet, idp;
1623 char info_string[256], *dest_server;
1625 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1627 /* Get server name */
1628 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1630 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1631 SILC_STATUS_ERR_NO_SUCH_SERVER);
1635 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1636 /* Send our reply */
1637 memset(info_string, 0, sizeof(info_string));
1638 snprintf(info_string, sizeof(info_string),
1639 "location: %s server: %s admin: %s <%s>",
1640 server->config->admin_info->location,
1641 server->config->admin_info->server_type,
1642 server->config->admin_info->admin_name,
1643 server->config->admin_info->admin_email);
1645 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1647 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1648 SILC_STATUS_OK, 0, 2,
1649 2, idp->data, idp->len,
1651 strlen(info_string));
1652 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1653 packet->data, packet->len, FALSE);
1655 silc_buffer_free(packet);
1656 silc_buffer_free(idp);
1658 /* Send this command to the requested server */
1660 if (server->server_type == SILC_SERVER && !server->standalone) {
1664 if (server->server_type == SILC_ROUTER) {
1670 silc_server_command_free(cmd);
1673 SILC_SERVER_CMD_FUNC(connect)
1677 /* Server side of command PING. This just replies to the ping. */
1679 SILC_SERVER_CMD_FUNC(ping)
1681 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1682 SilcServer server = cmd->server;
1687 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1690 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1693 SILC_STATUS_ERR_NO_SERVER_ID);
1696 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1700 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1701 /* Send our reply */
1702 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1705 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1706 SILC_STATUS_ERR_NO_SUCH_SERVER);
1713 silc_server_command_free(cmd);
1716 SILC_SERVER_CMD_FUNC(oper)
1720 /* Assembles USERS command and executes it. This is called when client
1721 joins to a channel and we wan't to send USERS command reply to the
1724 void silc_server_command_send_users(SilcServer server,
1725 SilcSocketConnection sock,
1726 SilcChannelEntry channel,
1729 SilcServerCommandContext cmd;
1730 SilcBuffer buffer, idp;
1731 SilcPacketContext *packet = silc_packet_context_alloc();
1733 SILC_LOG_DEBUG(("Start"));
1735 /* Create USERS command packet and process it. */
1736 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1737 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1738 1, idp->data, idp->len);
1740 packet->buffer = silc_buffer_copy(buffer);
1741 packet->sock = sock;
1742 packet->type = SILC_PACKET_COMMAND;
1744 cmd = silc_server_command_alloc();
1745 cmd->payload = silc_command_payload_parse(buffer);
1746 if (!cmd->payload) {
1748 silc_buffer_free(buffer);
1749 silc_buffer_free(idp);
1750 silc_packet_context_free(packet);
1753 cmd->args = silc_command_get_args(cmd->payload);
1754 cmd->server = server;
1755 cmd->sock = silc_socket_dup(sock);
1756 cmd->packet = silc_packet_context_dup(packet);
1757 cmd->pending = FALSE;
1760 /* If this function was called from pending command then instead of
1761 processing the command now, register a pending command callback which
1762 will process it after we've received the automatic USERS command
1763 reply which server will send in JOIN. */
1764 silc_server_command_pending(server, SILC_COMMAND_USERS, 0, NULL,
1765 silc_server_command_users, cmd);
1766 cmd->pending = TRUE;
1767 silc_buffer_free(buffer);
1768 silc_buffer_free(idp);
1772 /* Process USERS command. */
1773 silc_server_command_users((void *)cmd);
1775 silc_buffer_free(buffer);
1776 silc_buffer_free(idp);
1777 silc_packet_context_free(packet);
1780 /* Internal routine to join channel. The channel sent to this function
1781 has been either created or resolved from ID lists. This joins the sent
1782 client to the channel. */
1784 static void silc_server_command_join_channel(SilcServer server,
1785 SilcServerCommandContext cmd,
1786 SilcChannelEntry channel,
1787 SilcClientID *client_id,
1791 SilcSocketConnection sock = cmd->sock;
1793 unsigned int tmp_len;
1794 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1795 SilcClientEntry client;
1796 SilcChannelClientEntry chl;
1797 SilcBuffer reply, chidp, clidp, keyp;
1798 unsigned short ident = silc_command_get_ident(cmd->payload);
1800 SILC_LOG_DEBUG(("Start"));
1805 /* Get passphrase */
1806 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1808 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1809 memcpy(passphrase, tmp, tmp_len);
1813 * Check channel modes
1816 /* Check invite list if channel is invite-only channel */
1817 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1818 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1819 /* Invite list is specified. Check whether client is invited in the
1820 list. If not, then check whether it has been invited otherwise. */
1823 /* XXX client must be invited to be able to join the channel */
1827 /* Check ban list if set */
1828 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1832 /* Check the channel passphrase if set. */
1833 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1834 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1835 strlen(channel->mode_data.passphrase))) {
1836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1837 SILC_STATUS_ERR_BAD_PASSWORD);
1842 /* Check user count limit if set. */
1843 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1844 if (silc_list_count(channel->user_list) + 1 >
1845 channel->mode_data.user_limit) {
1846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1847 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1853 * Client is allowed to join to the channel. Make it happen.
1856 /* Get the client entry */
1857 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1858 client = (SilcClientEntry)sock->user_data;
1860 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1863 /* XXX actually this is useless since router finds always cell's
1864 local clients from its local lists. */
1865 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1872 /* Check whether the client already is on the channel */
1873 if (silc_server_client_on_channel(client, channel)) {
1874 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1875 SILC_STATUS_ERR_USER_ON_CHANNEL);
1879 /* Generate new channel key as protocol dictates */
1880 if (!created || !channel->channel_key)
1881 silc_server_create_channel_key(server, channel, 0);
1883 /* Send the channel key. This is broadcasted to the channel but is not
1884 sent to the client who is joining to the channel. */
1885 silc_server_send_channel_key(server, NULL, channel,
1886 server->server_type == SILC_ROUTER ?
1887 FALSE : server->standalone);
1889 /* Join the client to the channel by adding it to channel's user list.
1890 Add also the channel to client entry's channels list for fast cross-
1892 chl = silc_calloc(1, sizeof(*chl));
1894 chl->client = client;
1895 chl->channel = channel;
1896 silc_list_add(channel->user_list, chl);
1897 silc_list_add(client->channels, chl);
1899 /* Encode Client ID Payload of the original client who wants to join */
1900 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1902 /* Encode command reply packet */
1903 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1904 SILC_PUT32_MSB(channel->mode, mode);
1905 SILC_PUT32_MSB(created, tmp2);
1906 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1907 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1908 SILC_ID_CHANNEL_LEN,
1909 channel->channel_key->cipher->name,
1910 channel->key_len / 8, channel->key);
1912 if (!channel->topic) {
1914 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1915 SILC_STATUS_OK, ident, 5,
1916 2, channel->channel_name,
1917 strlen(channel->channel_name),
1918 3, chidp->data, chidp->len,
1921 6, keyp->data, keyp->len);
1924 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1925 SILC_STATUS_OK, ident, 6,
1926 2, channel->channel_name,
1927 strlen(channel->channel_name),
1928 3, chidp->data, chidp->len,
1931 6, keyp->data, keyp->len,
1933 strlen(channel->topic));
1936 /* Send command reply */
1937 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1938 reply->data, reply->len, FALSE);
1940 if (!cmd->pending) {
1941 /* Send JOIN notify to locally connected clients on the channel */
1942 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1943 SILC_NOTIFY_TYPE_JOIN, 2,
1944 clidp->data, clidp->len,
1945 chidp->data, chidp->len);
1947 /* Send JOIN notify packet to our primary router */
1948 if (!server->standalone)
1949 silc_server_send_notify_join(server, server->router->connection,
1950 server->server_type == SILC_ROUTER ?
1951 TRUE : FALSE, channel, client->id,
1952 SILC_ID_CLIENT_LEN);
1955 /* Send USERS command reply to the joined channel so the user sees who
1956 is currently on the channel. */
1957 silc_server_command_send_users(server, sock, channel, cmd->pending);
1959 silc_buffer_free(reply);
1960 silc_buffer_free(clidp);
1961 silc_buffer_free(chidp);
1962 silc_buffer_free(keyp);
1966 silc_free(passphrase);
1969 /* Server side of command JOIN. Joins client into requested channel. If
1970 the channel does not exist it will be created. */
1972 SILC_SERVER_CMD_FUNC(join)
1974 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1975 SilcServer server = cmd->server;
1977 char *tmp, *channel_name = NULL, *cipher = NULL;
1978 SilcChannelEntry channel;
1979 unsigned int umode = 0;
1980 int created = FALSE;
1981 SilcClientID *client_id;
1983 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1985 /* Get channel name */
1986 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1988 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1989 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1994 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1995 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1996 SILC_STATUS_ERR_BAD_CHANNEL);
1997 silc_free(channel_name);
2001 /* Get Client ID of the client who is joining to the channel */
2002 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2005 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2008 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2010 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2011 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2015 /* Get cipher name */
2016 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2018 /* See if the channel exists */
2019 channel = silc_idlist_find_channel_by_name(server->local_list,
2020 channel_name, NULL);
2022 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2023 /* If this is coming from client the Client ID in the command packet must
2024 be same as the client's ID. */
2025 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2026 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2027 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2029 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2035 /* Channel not found */
2037 /* If we are standalone server we don't have a router, we just create
2038 the channel by ourselves. */
2039 if (server->standalone) {
2040 channel = silc_server_create_new_channel(server, server->id, cipher,
2041 channel_name, TRUE);
2042 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2047 /* The channel does not exist on our server. If we are normal server
2048 we will send JOIN command to our router which will handle the
2049 joining procedure (either creates the channel if it doesn't exist
2050 or joins the client to it). */
2051 if (server->server_type == SILC_SERVER) {
2053 unsigned short old_ident;
2055 old_ident = silc_command_get_ident(cmd->payload);
2056 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2057 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2059 /* Send JOIN command to our router */
2060 silc_server_packet_send(server, (SilcSocketConnection)
2061 server->router->connection,
2062 SILC_PACKET_COMMAND, cmd->packet->flags,
2063 tmpbuf->data, tmpbuf->len, TRUE);
2065 /* Reprocess this packet after received reply from router */
2066 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2067 silc_command_get_ident(cmd->payload),
2068 silc_server_command_destructor,
2069 silc_server_command_join,
2070 silc_server_command_dup(cmd));
2071 cmd->pending = TRUE;
2075 /* We are router and the channel does not seem exist so we will check
2076 our global list as well for the channel. */
2077 channel = silc_idlist_find_channel_by_name(server->global_list,
2078 channel_name, NULL);
2080 /* Channel really does not exist, create it */
2081 channel = silc_server_create_new_channel(server, server->id, cipher,
2082 channel_name, TRUE);
2083 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2090 /* Channel not found */
2092 /* If the command came from router and/or we are normal server then
2093 something went wrong with the joining as the channel was not found.
2094 We can't do anything else but ignore this. */
2095 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2096 server->server_type == SILC_SERVER)
2099 /* We are router and the channel does not seem exist so we will check
2100 our global list as well for the channel. */
2101 channel = silc_idlist_find_channel_by_name(server->global_list,
2102 channel_name, NULL);
2104 /* Channel really does not exist, create it */
2105 channel = silc_server_create_new_channel(server, server->id, cipher,
2106 channel_name, TRUE);
2107 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2113 /* If the channel does not have global users and is also empty it means the
2114 channel was created globally (by our router) and the client will be the
2115 channel founder and operator. */
2116 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2117 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2118 created = TRUE; /* Created globally by our router */
2121 /* Join to the channel */
2122 silc_server_command_join_channel(server, cmd, channel, client_id,
2125 silc_free(client_id);
2128 silc_server_command_free(cmd);
2131 /* Server side of command MOTD. Sends server's current "message of the
2132 day" to the client. */
2134 SILC_SERVER_CMD_FUNC(motd)
2136 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2137 SilcServer server = cmd->server;
2141 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2143 /* XXX show currently only our motd */
2145 if (server->config && server->config->motd &&
2146 server->config->motd->motd_file) {
2149 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2154 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2160 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2165 silc_server_command_free(cmd);
2168 SILC_SERVER_CMD_FUNC(umode)
2172 /* Checks that client has rights to add or remove channel modes. If any
2173 of the checks fails FALSE is returned. */
2175 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2176 SilcChannelClientEntry client,
2179 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2180 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2182 /* Check whether has rights to change anything */
2183 if (!is_op && !is_fo)
2186 /* Check whether has rights to change everything */
2190 /* We know that client is channel operator, check that they are not
2191 changing anything that requires channel founder rights. Rest of the
2192 modes are available automatically for channel operator. */
2194 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2195 if (is_op && !is_fo)
2198 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2199 if (is_op && !is_fo)
2204 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2205 if (is_op && !is_fo)
2208 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2209 if (is_op && !is_fo)
2214 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2215 if (is_op && !is_fo)
2218 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2219 if (is_op && !is_fo)
2227 /* Server side command of CMODE. Changes channel mode */
2229 SILC_SERVER_CMD_FUNC(cmode)
2231 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2232 SilcServer server = cmd->server;
2233 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2234 SilcChannelID *channel_id;
2235 SilcChannelEntry channel;
2236 SilcChannelClientEntry chl;
2237 SilcBuffer packet, cidp;
2238 unsigned char *tmp, *tmp_id, *tmp_mask;
2239 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2241 SILC_LOG_DEBUG(("Start"));
2243 argc = silc_argument_get_arg_num(cmd->args);
2245 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2246 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2250 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2251 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2255 /* Get Channel ID */
2256 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2259 SILC_STATUS_ERR_NO_CHANNEL_ID);
2262 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2264 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2265 SILC_STATUS_ERR_NO_CHANNEL_ID);
2269 /* Get the channel mode mask */
2270 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2273 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2276 SILC_GET32_MSB(mode_mask, tmp_mask);
2278 /* Get channel entry */
2279 channel = silc_idlist_find_channel_by_id(server->local_list,
2282 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2283 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2287 /* Check whether this client is on the channel */
2288 if (!silc_server_client_on_channel(client, channel)) {
2289 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2290 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2294 /* Get entry to the channel user list */
2295 silc_list_start(channel->user_list);
2296 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2297 if (chl->client == client)
2300 /* Check that client has rights to change any requested channel modes */
2301 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2302 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2303 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2308 * Check the modes. Modes that requires nothing special operation are
2312 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2313 /* Channel uses private keys to protect traffic. Client(s) has set the
2314 key locally they want to use, server does not know that key. */
2315 /* Nothing interesting to do here now */
2317 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2318 /* The mode is removed and we need to generate and distribute
2319 new channel key. Clients are not using private channel keys
2320 anymore after this. */
2322 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2325 /* Re-generate channel key */
2326 silc_server_create_channel_key(server, channel, 0);
2328 /* Encode channel key payload to be distributed on the channel */
2330 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2331 strlen(channel->channel_key->
2333 channel->channel_key->cipher->name,
2334 channel->key_len / 8, channel->key);
2336 /* If we are normal server then we will send it to our router. If we
2337 are router we will send it to all local servers that has clients on
2339 if (server->server_type == SILC_SERVER) {
2340 if (!server->standalone)
2341 silc_server_packet_send(server,
2342 cmd->server->router->connection,
2343 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2349 /* Send to locally connected clients on the channel */
2350 silc_server_packet_send_local_channel(server, channel,
2351 SILC_PACKET_CHANNEL_KEY, 0,
2352 packet->data, packet->len, FALSE);
2353 silc_buffer_free(packet);
2357 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2358 /* User limit is set on channel */
2359 unsigned int user_limit;
2361 /* Get user limit */
2362 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2364 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2365 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2366 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2370 SILC_GET32_MSB(user_limit, tmp);
2371 channel->mode_data.user_limit = user_limit;
2374 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2375 /* User limit mode is unset. Remove user limit */
2376 channel->mode_data.user_limit = 0;
2379 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2380 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2381 /* Passphrase has been set to channel */
2383 /* Get the passphrase */
2384 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2387 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2391 /* Save the passphrase */
2392 channel->mode_data.passphrase = strdup(tmp);
2395 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2396 /* Passphrase mode is unset. remove the passphrase */
2397 if (channel->mode_data.passphrase) {
2398 silc_free(channel->mode_data.passphrase);
2399 channel->mode_data.passphrase = NULL;
2404 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2405 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2406 /* Ban list is specified for channel */
2409 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2411 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2412 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2416 /* XXX check that channel founder is not banned */
2418 /* Save the ban list */
2419 channel->mode_data.ban_list = strdup(tmp);
2422 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2423 /* Ban mode is unset. Remove the entire ban list */
2424 if (channel->mode_data.ban_list) {
2425 silc_free(channel->mode_data.ban_list);
2426 channel->mode_data.ban_list = NULL;
2431 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2432 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2433 /* Invite list is specified for channel */
2435 /* Get invite list */
2436 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2439 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2443 /* Save the invite linst */
2444 channel->mode_data.invite_list = strdup(tmp);
2447 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2448 /* Invite list mode is unset. Remove the entire invite list */
2449 if (channel->mode_data.invite_list) {
2450 silc_free(channel->mode_data.invite_list);
2451 channel->mode_data.invite_list = NULL;
2456 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2457 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2458 /* Cipher to use protect the traffic */
2459 unsigned int key_len = 128;
2463 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2466 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2470 cp = strchr(tmp, ':');
2476 /* XXX Duplicated code, make own function for this!! */
2478 /* Delete old cipher and allocate the new one */
2479 silc_cipher_free(channel->channel_key);
2480 silc_cipher_alloc(tmp, &channel->channel_key);
2486 /* Re-generate channel key */
2487 silc_server_create_channel_key(server, channel, key_len);
2489 /* Encode channel key payload to be distributed on the channel */
2491 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2492 strlen(channel->channel_key->
2494 channel->channel_key->cipher->name,
2495 channel->key_len / 8, channel->key);
2497 /* If we are normal server then we will send it to our router. If we
2498 are router we will send it to all local servers that has clients on
2500 if (server->server_type == SILC_SERVER) {
2501 if (!server->standalone)
2502 silc_server_packet_send(server,
2503 cmd->server->router->connection,
2504 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2510 /* Send to locally connected clients on the channel */
2511 silc_server_packet_send_local_channel(server, channel,
2512 SILC_PACKET_CHANNEL_KEY, 0,
2513 packet->data, packet->len, FALSE);
2514 silc_buffer_free(packet);
2517 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2518 /* Cipher mode is unset. Remove the cipher and revert back to
2521 if (channel->mode_data.cipher) {
2522 silc_free(channel->mode_data.cipher);
2523 channel->mode_data.cipher = NULL;
2524 channel->mode_data.key_len = 0;
2527 /* Generate new cipher and key for the channel */
2529 /* XXX Duplicated code, make own function for this!! */
2531 /* Delete old cipher and allocate default one */
2532 silc_cipher_free(channel->channel_key);
2533 if (!channel->cipher)
2534 silc_cipher_alloc("twofish", &channel->channel_key);
2536 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2538 /* Re-generate channel key */
2539 silc_server_create_channel_key(server, channel, 0);
2541 /* Encode channel key payload to be distributed on the channel */
2543 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2544 strlen(channel->channel_key->
2546 channel->channel_key->cipher->name,
2547 channel->key_len / 8, channel->key);
2549 /* If we are normal server then we will send it to our router. If we
2550 are router we will send it to all local servers that has clients on
2552 if (server->server_type == SILC_SERVER) {
2553 if (!server->standalone)
2554 silc_server_packet_send(server,
2555 cmd->server->router->connection,
2556 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2562 /* Send to locally connected clients on the channel */
2563 silc_server_packet_send_local_channel(server, channel,
2564 SILC_PACKET_CHANNEL_KEY, 0,
2565 packet->data, packet->len, FALSE);
2566 silc_buffer_free(packet);
2570 /* Finally, set the mode */
2571 channel->mode = mode_mask;
2573 /* Send CMODE_CHANGE notify */
2574 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2575 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2576 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2577 cidp->data, cidp->len,
2580 /* Set CMODE notify type to network */
2581 if (!server->standalone)
2582 silc_server_send_notify_cmode(server, server->router->connection,
2583 server->server_type == SILC_ROUTER ?
2584 TRUE : FALSE, channel,
2585 mode_mask, client->id, SILC_ID_CLIENT_LEN);
2587 /* Send command reply to sender */
2588 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2589 SILC_STATUS_OK, 0, 1,
2591 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2592 packet->data, packet->len, FALSE);
2594 silc_buffer_free(packet);
2595 silc_free(channel_id);
2599 silc_server_command_free(cmd);
2602 /* Server side of CUMODE command. Changes client's mode on a channel. */
2604 SILC_SERVER_CMD_FUNC(cumode)
2606 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2607 SilcServer server = cmd->server;
2608 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2609 SilcChannelID *channel_id;
2610 SilcClientID *client_id;
2611 SilcChannelEntry channel;
2612 SilcClientEntry target_client;
2613 SilcChannelClientEntry chl;
2614 SilcBuffer packet, idp;
2615 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2616 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
2619 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2621 /* Get Channel ID */
2622 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2624 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2625 SILC_STATUS_ERR_NO_CHANNEL_ID);
2628 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
2630 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2631 SILC_STATUS_ERR_NO_CHANNEL_ID);
2635 /* Get channel entry */
2636 channel = silc_idlist_find_channel_by_id(server->local_list,
2639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2640 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2644 /* Check whether sender is on the channel */
2645 if (!silc_server_client_on_channel(client, channel)) {
2646 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2647 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2651 /* Check that client has rights to change other's rights */
2652 silc_list_start(channel->user_list);
2653 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2654 if (chl->client == client) {
2655 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2656 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2657 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2658 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2662 sender_mask = chl->mode;
2667 /* Get the target client's channel mode mask */
2668 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2671 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2674 SILC_GET32_MSB(target_mask, tmp_mask);
2676 /* Get target Client ID */
2677 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2680 SILC_STATUS_ERR_NO_CHANNEL_ID);
2683 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2685 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2686 SILC_STATUS_ERR_NO_CHANNEL_ID);
2690 /* Get target client's entry */
2691 target_client = silc_idlist_find_client_by_id(server->local_list,
2693 if (!target_client) {
2694 target_client = silc_idlist_find_client_by_id(server->global_list,
2698 /* Check whether target client is on the channel */
2699 if (!silc_server_client_on_channel(target_client, channel)) {
2700 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2701 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2705 /* Get entry to the channel user list */
2706 silc_list_start(channel->user_list);
2707 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2708 if (chl->client == target_client)
2715 /* If the target client is founder, no one else can change their mode
2717 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2719 SILC_STATUS_ERR_NOT_YOU);
2723 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2724 /* Cannot promote anyone to channel founder */
2725 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2726 SILC_STATUS_ERR_NOT_YOU);
2729 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2730 if (target_client == client) {
2731 /* Remove channel founder rights from itself */
2732 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2736 SILC_STATUS_ERR_NOT_YOU);
2742 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2743 /* Promote to operator */
2744 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2745 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2749 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2750 /* Demote to normal user */
2751 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2756 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2758 /* Send notify to channel, notify only if mode was actually changed. */
2760 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2761 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2762 idp->data, idp->len,
2766 /* Set CUMODE notify type to network */
2767 if (!server->standalone)
2768 silc_server_send_notify_cumode(server, server->router->connection,
2769 server->server_type == SILC_ROUTER ?
2770 TRUE : FALSE, channel,
2771 target_mask, client->id,
2774 SILC_ID_CLIENT_LEN);
2777 /* Send command reply to sender */
2778 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2779 SILC_STATUS_OK, 0, 2,
2781 3, tmp_id, tmp_len);
2782 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2783 packet->data, packet->len, FALSE);
2785 silc_buffer_free(packet);
2786 silc_free(channel_id);
2787 silc_free(client_id);
2788 silc_buffer_free(idp);
2791 silc_server_command_free(cmd);
2794 /* Server side of KICK command. Kicks client out of channel. */
2796 SILC_SERVER_CMD_FUNC(kick)
2800 SILC_SERVER_CMD_FUNC(restart)
2804 SILC_SERVER_CMD_FUNC(close)
2808 SILC_SERVER_CMD_FUNC(die)
2812 SILC_SERVER_CMD_FUNC(silcoper)
2816 /* Server side command of LEAVE. Removes client from a channel. */
2818 SILC_SERVER_CMD_FUNC(leave)
2820 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2821 SilcServer server = cmd->server;
2822 SilcSocketConnection sock = cmd->sock;
2823 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2825 SilcChannelEntry channel;
2827 unsigned int i, len;
2830 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2832 /* Get Channel ID */
2833 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2836 SILC_STATUS_ERR_NO_CHANNEL_ID);
2839 id = silc_id_payload_parse_id(tmp, len);
2841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2842 SILC_STATUS_ERR_NO_CHANNEL_ID);
2846 /* Get channel entry */
2847 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2849 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2850 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2854 /* Check whether this client is on the channel */
2855 if (!silc_server_client_on_channel(id_entry, channel)) {
2856 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2857 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2861 /* Notify routers that they should remove this client from their list
2862 of clients on the channel. Send LEAVE notify type. */
2863 if (!server->standalone)
2864 silc_server_send_notify_leave(server, server->router->connection,
2865 server->server_type == SILC_ROUTER ?
2866 TRUE : FALSE, channel, id_entry->id,
2867 SILC_ID_CLIENT_LEN);
2869 /* Remove client from channel */
2870 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2872 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2875 /* If the channel does not exist anymore we won't send anything */
2879 /* Re-generate channel key */
2880 silc_server_create_channel_key(server, channel, 0);
2882 /* Encode channel key payload to be distributed on the channel */
2884 silc_channel_key_payload_encode(len, tmp,
2885 strlen(channel->channel_key->cipher->name),
2886 channel->channel_key->cipher->name,
2887 channel->key_len / 8, channel->key);
2889 /* If we are normal server then we will send it to our router. If we
2890 are router we will send it to all local servers that has clients on
2892 if (server->server_type == SILC_SERVER) {
2893 if (!server->standalone)
2894 silc_server_packet_send(server,
2895 cmd->server->router->connection,
2896 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2897 packet->len, FALSE);
2902 /* Send to locally connected clients on the channel */
2903 silc_server_packet_send_local_channel(server, channel,
2904 SILC_PACKET_CHANNEL_KEY, 0,
2905 packet->data, packet->len, FALSE);
2907 silc_buffer_free(packet);
2911 silc_server_command_free(cmd);
2914 /* Server side of command USERS. Resolves clients and their USERS currently
2915 joined on the requested channel. The list of Client ID's and their modes
2916 on the channel is sent back. */
2918 SILC_SERVER_CMD_FUNC(users)
2920 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2921 SilcServer server = cmd->server;
2922 SilcChannelEntry channel;
2923 SilcChannelClientEntry chl;
2926 unsigned char *channel_id;
2927 unsigned int channel_id_len;
2928 SilcBuffer client_id_list;
2929 SilcBuffer client_mode_list;
2931 unsigned char lc[4];
2932 unsigned int list_count = 0;
2933 unsigned short ident = silc_command_get_ident(cmd->payload);
2935 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
2937 /* Get Channel ID */
2938 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
2940 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2941 SILC_STATUS_ERR_NO_CHANNEL_ID);
2944 id = silc_id_payload_parse_id(channel_id, channel_id_len);
2946 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2947 SILC_STATUS_ERR_NO_CHANNEL_ID);
2951 /* If we are server and we don't know about this channel we will send
2952 the command to our router. If we know about the channel then we also
2953 have the list of users already. */
2954 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2956 if (server->server_type == SILC_SERVER && !server->standalone &&
2960 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2961 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2963 /* Send USERS command */
2964 silc_server_packet_send(server, server->router->connection,
2965 SILC_PACKET_COMMAND, cmd->packet->flags,
2966 tmpbuf->data, tmpbuf->len, TRUE);
2968 /* Reprocess this packet after received reply */
2969 silc_server_command_pending(server, SILC_COMMAND_USERS,
2970 silc_command_get_ident(cmd->payload),
2971 silc_server_command_destructor,
2972 silc_server_command_users,
2973 silc_server_command_dup(cmd));
2974 cmd->pending = TRUE;
2975 silc_command_set_ident(cmd->payload, ident);
2977 silc_buffer_free(tmpbuf);
2982 /* We are router and we will check the global list as well. */
2983 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2985 /* Channel really does not exist */
2986 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2987 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2992 /* Assemble the lists now */
2994 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2995 silc_list_count(channel->user_list));
2996 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2998 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2999 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
3001 silc_list_start(channel->user_list);
3002 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3004 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
3005 silc_buffer_put(client_id_list, idp->data, idp->len);
3006 silc_buffer_pull(client_id_list, idp->len);
3007 silc_buffer_free(idp);
3009 /* Client's mode on channel */
3010 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
3011 silc_buffer_pull(client_mode_list, 4);
3015 silc_buffer_push(client_id_list,
3016 client_id_list->data - client_id_list->head);
3017 silc_buffer_push(client_mode_list,
3018 client_mode_list->data - client_mode_list->head);
3021 SILC_PUT32_MSB(list_count, lc);
3024 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3025 SILC_STATUS_OK, 0, 4,
3026 2, channel_id, channel_id_len,
3028 4, client_id_list->data,
3029 client_id_list->len,
3030 5, client_mode_list->data,
3031 client_mode_list->len);
3032 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3033 packet->data, packet->len, FALSE);
3035 silc_buffer_free(packet);
3036 silc_buffer_free(client_id_list);
3037 silc_buffer_free(client_mode_list);
3041 silc_server_command_free(cmd);