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);
1578 SilcSocketConnection sock;
1582 /* Quits connection to client. This gets called if client won't
1583 close the connection even when it has issued QUIT command. */
1585 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1587 QuitInternal q = (QuitInternal)context;
1589 /* Free all client specific data, such as client entry and entires
1590 on channels this client may be on. */
1591 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1593 q->sock->user_data = NULL;
1595 /* Close the connection on our side */
1596 silc_server_close_connection(q->server, q->sock);
1598 silc_free(q->signoff);
1602 /* Quits SILC session. This is the normal way to disconnect client. */
1604 SILC_SERVER_CMD_FUNC(quit)
1606 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1607 SilcServer server = cmd->server;
1608 SilcSocketConnection sock = cmd->sock;
1610 unsigned char *tmp = NULL;
1611 unsigned int len = 0;
1613 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
1615 /* Get destination ID */
1616 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1620 q = silc_calloc(1, sizeof(*q));
1623 q->signoff = tmp ? strdup(tmp) : NULL;
1625 /* We quit the connection with little timeout */
1626 silc_task_register(server->timeout_queue, sock->sock,
1627 silc_server_command_quit_cb, (void *)q,
1628 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1630 silc_server_command_free(cmd);
1633 SILC_SERVER_CMD_FUNC(kill)
1637 /* Server side of command INFO. This sends information about us to
1638 the client. If client requested specific server we will send the
1639 command to that server. */
1641 SILC_SERVER_CMD_FUNC(info)
1643 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1644 SilcServer server = cmd->server;
1645 SilcBuffer packet, idp;
1646 char info_string[256], *dest_server;
1648 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1650 /* Get server name */
1651 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1653 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1654 SILC_STATUS_ERR_NO_SUCH_SERVER);
1658 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1659 /* Send our reply */
1660 memset(info_string, 0, sizeof(info_string));
1661 snprintf(info_string, sizeof(info_string),
1662 "location: %s server: %s admin: %s <%s>",
1663 server->config->admin_info->location,
1664 server->config->admin_info->server_type,
1665 server->config->admin_info->admin_name,
1666 server->config->admin_info->admin_email);
1668 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1670 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1671 SILC_STATUS_OK, 0, 2,
1672 2, idp->data, idp->len,
1674 strlen(info_string));
1675 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1676 packet->data, packet->len, FALSE);
1678 silc_buffer_free(packet);
1679 silc_buffer_free(idp);
1681 /* Send this command to the requested server */
1683 if (server->server_type == SILC_SERVER && !server->standalone) {
1687 if (server->server_type == SILC_ROUTER) {
1693 silc_server_command_free(cmd);
1696 SILC_SERVER_CMD_FUNC(connect)
1700 /* Server side of command PING. This just replies to the ping. */
1702 SILC_SERVER_CMD_FUNC(ping)
1704 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1705 SilcServer server = cmd->server;
1710 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1713 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1716 SILC_STATUS_ERR_NO_SERVER_ID);
1719 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1723 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1724 /* Send our reply */
1725 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1728 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1729 SILC_STATUS_ERR_NO_SUCH_SERVER);
1736 silc_server_command_free(cmd);
1739 SILC_SERVER_CMD_FUNC(oper)
1743 /* Assembles USERS command and executes it. This is called when client
1744 joins to a channel and we wan't to send USERS command reply to the
1747 void silc_server_command_send_users(SilcServer server,
1748 SilcSocketConnection sock,
1749 SilcChannelEntry channel,
1752 SilcServerCommandContext cmd;
1753 SilcBuffer buffer, idp;
1754 SilcPacketContext *packet = silc_packet_context_alloc();
1756 SILC_LOG_DEBUG(("Start"));
1758 /* Create USERS command packet and process it. */
1759 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1760 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1761 1, idp->data, idp->len);
1763 packet->buffer = silc_buffer_copy(buffer);
1764 packet->sock = sock;
1765 packet->type = SILC_PACKET_COMMAND;
1767 cmd = silc_server_command_alloc();
1768 cmd->payload = silc_command_payload_parse(buffer);
1769 if (!cmd->payload) {
1771 silc_buffer_free(buffer);
1772 silc_buffer_free(idp);
1773 silc_packet_context_free(packet);
1776 cmd->args = silc_command_get_args(cmd->payload);
1777 cmd->server = server;
1778 cmd->sock = silc_socket_dup(sock);
1779 cmd->packet = silc_packet_context_dup(packet);
1780 cmd->pending = FALSE;
1783 /* If this function was called from pending command then instead of
1784 processing the command now, register a pending command callback which
1785 will process it after we've received the automatic USERS command
1786 reply which server will send in JOIN. */
1787 silc_server_command_pending(server, SILC_COMMAND_USERS, 0, NULL,
1788 silc_server_command_users, cmd);
1789 cmd->pending = TRUE;
1790 silc_buffer_free(buffer);
1791 silc_buffer_free(idp);
1795 /* Process USERS command. */
1796 silc_server_command_users((void *)cmd);
1798 silc_buffer_free(buffer);
1799 silc_buffer_free(idp);
1800 silc_packet_context_free(packet);
1803 /* Internal routine to join channel. The channel sent to this function
1804 has been either created or resolved from ID lists. This joins the sent
1805 client to the channel. */
1807 static void silc_server_command_join_channel(SilcServer server,
1808 SilcServerCommandContext cmd,
1809 SilcChannelEntry channel,
1810 SilcClientID *client_id,
1814 SilcSocketConnection sock = cmd->sock;
1816 unsigned int tmp_len;
1817 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1818 SilcClientEntry client;
1819 SilcChannelClientEntry chl;
1820 SilcBuffer reply, chidp, clidp, keyp;
1821 unsigned short ident = silc_command_get_ident(cmd->payload);
1823 SILC_LOG_DEBUG(("Start"));
1828 /* Get passphrase */
1829 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1831 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1832 memcpy(passphrase, tmp, tmp_len);
1836 * Check channel modes
1839 /* Check invite list if channel is invite-only channel */
1840 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1841 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1842 /* Invite list is specified. Check whether client is invited in the
1843 list. If not, then check whether it has been invited otherwise. */
1846 /* XXX client must be invited to be able to join the channel */
1850 /* Check ban list if set */
1851 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1855 /* Check the channel passphrase if set. */
1856 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1857 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1858 strlen(channel->mode_data.passphrase))) {
1859 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1860 SILC_STATUS_ERR_BAD_PASSWORD);
1865 /* Check user count limit if set. */
1866 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1867 if (silc_list_count(channel->user_list) + 1 >
1868 channel->mode_data.user_limit) {
1869 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1870 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1876 * Client is allowed to join to the channel. Make it happen.
1879 /* Get the client entry */
1880 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1881 client = (SilcClientEntry)sock->user_data;
1883 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1886 /* XXX actually this is useless since router finds always cell's
1887 local clients from its local lists. */
1888 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1895 /* Check whether the client already is on the channel */
1896 if (silc_server_client_on_channel(client, channel)) {
1897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1898 SILC_STATUS_ERR_USER_ON_CHANNEL);
1902 /* Generate new channel key as protocol dictates */
1903 if (!created || !channel->channel_key)
1904 silc_server_create_channel_key(server, channel, 0);
1906 /* Send the channel key. This is broadcasted to the channel but is not
1907 sent to the client who is joining to the channel. */
1908 silc_server_send_channel_key(server, NULL, channel,
1909 server->server_type == SILC_ROUTER ?
1910 FALSE : server->standalone);
1912 /* Join the client to the channel by adding it to channel's user list.
1913 Add also the channel to client entry's channels list for fast cross-
1915 chl = silc_calloc(1, sizeof(*chl));
1917 chl->client = client;
1918 chl->channel = channel;
1919 silc_list_add(channel->user_list, chl);
1920 silc_list_add(client->channels, chl);
1922 /* Encode Client ID Payload of the original client who wants to join */
1923 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1925 /* Encode command reply packet */
1926 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1927 SILC_PUT32_MSB(channel->mode, mode);
1928 SILC_PUT32_MSB(created, tmp2);
1929 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1930 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1931 SILC_ID_CHANNEL_LEN,
1932 channel->channel_key->cipher->name,
1933 channel->key_len / 8, channel->key);
1935 if (!channel->topic) {
1937 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1938 SILC_STATUS_OK, ident, 5,
1939 2, channel->channel_name,
1940 strlen(channel->channel_name),
1941 3, chidp->data, chidp->len,
1944 6, keyp->data, keyp->len);
1947 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1948 SILC_STATUS_OK, ident, 6,
1949 2, channel->channel_name,
1950 strlen(channel->channel_name),
1951 3, chidp->data, chidp->len,
1954 6, keyp->data, keyp->len,
1956 strlen(channel->topic));
1959 /* Send command reply */
1960 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1961 reply->data, reply->len, FALSE);
1963 if (!cmd->pending) {
1964 /* Send JOIN notify to locally connected clients on the channel */
1965 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1966 SILC_NOTIFY_TYPE_JOIN, 2,
1967 clidp->data, clidp->len,
1968 chidp->data, chidp->len);
1970 /* Send JOIN notify packet to our primary router */
1971 if (!server->standalone)
1972 silc_server_send_notify_join(server, server->router->connection,
1973 server->server_type == SILC_ROUTER ?
1974 TRUE : FALSE, channel, client->id,
1975 SILC_ID_CLIENT_LEN);
1978 /* Send USERS command reply to the joined channel so the user sees who
1979 is currently on the channel. */
1980 silc_server_command_send_users(server, sock, channel, cmd->pending);
1982 silc_buffer_free(reply);
1983 silc_buffer_free(clidp);
1984 silc_buffer_free(chidp);
1985 silc_buffer_free(keyp);
1989 silc_free(passphrase);
1992 /* Server side of command JOIN. Joins client into requested channel. If
1993 the channel does not exist it will be created. */
1995 SILC_SERVER_CMD_FUNC(join)
1997 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1998 SilcServer server = cmd->server;
2000 char *tmp, *channel_name = NULL, *cipher = NULL;
2001 SilcChannelEntry channel;
2002 unsigned int umode = 0;
2003 int created = FALSE;
2004 SilcClientID *client_id;
2006 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2008 /* Get channel name */
2009 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2011 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2012 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2017 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2019 SILC_STATUS_ERR_BAD_CHANNEL);
2020 silc_free(channel_name);
2024 /* Get Client ID of the client who is joining to the channel */
2025 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2027 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2028 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2031 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2033 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2034 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2038 /* Get cipher name */
2039 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2041 /* See if the channel exists */
2042 channel = silc_idlist_find_channel_by_name(server->local_list,
2043 channel_name, NULL);
2045 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2046 /* If this is coming from client the Client ID in the command packet must
2047 be same as the client's ID. */
2048 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2049 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2050 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2052 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2058 /* Channel not found */
2060 /* If we are standalone server we don't have a router, we just create
2061 the channel by ourselves. */
2062 if (server->standalone) {
2063 channel = silc_server_create_new_channel(server, server->id, cipher,
2064 channel_name, TRUE);
2065 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2070 /* The channel does not exist on our server. If we are normal server
2071 we will send JOIN command to our router which will handle the
2072 joining procedure (either creates the channel if it doesn't exist
2073 or joins the client to it). */
2074 if (server->server_type == SILC_SERVER) {
2076 unsigned short old_ident;
2078 old_ident = silc_command_get_ident(cmd->payload);
2079 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2080 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2082 /* Send JOIN command to our router */
2083 silc_server_packet_send(server, (SilcSocketConnection)
2084 server->router->connection,
2085 SILC_PACKET_COMMAND, cmd->packet->flags,
2086 tmpbuf->data, tmpbuf->len, TRUE);
2088 /* Reprocess this packet after received reply from router */
2089 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2090 silc_command_get_ident(cmd->payload),
2091 silc_server_command_destructor,
2092 silc_server_command_join,
2093 silc_server_command_dup(cmd));
2094 cmd->pending = TRUE;
2098 /* We are router and the channel does not seem exist so we will check
2099 our global list as well for the channel. */
2100 channel = silc_idlist_find_channel_by_name(server->global_list,
2101 channel_name, NULL);
2103 /* Channel really does not exist, create it */
2104 channel = silc_server_create_new_channel(server, server->id, cipher,
2105 channel_name, TRUE);
2106 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2113 /* Channel not found */
2115 /* If the command came from router and/or we are normal server then
2116 something went wrong with the joining as the channel was not found.
2117 We can't do anything else but ignore this. */
2118 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2119 server->server_type == SILC_SERVER)
2122 /* We are router and the channel does not seem exist so we will check
2123 our global list as well for the channel. */
2124 channel = silc_idlist_find_channel_by_name(server->global_list,
2125 channel_name, NULL);
2127 /* Channel really does not exist, create it */
2128 channel = silc_server_create_new_channel(server, server->id, cipher,
2129 channel_name, TRUE);
2130 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2136 /* If the channel does not have global users and is also empty it means the
2137 channel was created globally (by our router) and the client will be the
2138 channel founder and operator. */
2139 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2140 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2141 created = TRUE; /* Created globally by our router */
2144 /* Join to the channel */
2145 silc_server_command_join_channel(server, cmd, channel, client_id,
2148 silc_free(client_id);
2151 silc_server_command_free(cmd);
2154 /* Server side of command MOTD. Sends server's current "message of the
2155 day" to the client. */
2157 SILC_SERVER_CMD_FUNC(motd)
2159 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2160 SilcServer server = cmd->server;
2164 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2166 /* XXX show currently only our motd */
2168 if (server->config && server->config->motd &&
2169 server->config->motd->motd_file) {
2172 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2177 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2188 silc_server_command_free(cmd);
2191 SILC_SERVER_CMD_FUNC(umode)
2195 /* Checks that client has rights to add or remove channel modes. If any
2196 of the checks fails FALSE is returned. */
2198 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2199 SilcChannelClientEntry client,
2202 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2203 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2205 /* Check whether has rights to change anything */
2206 if (!is_op && !is_fo)
2209 /* Check whether has rights to change everything */
2213 /* We know that client is channel operator, check that they are not
2214 changing anything that requires channel founder rights. Rest of the
2215 modes are available automatically for channel operator. */
2217 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2218 if (is_op && !is_fo)
2221 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2222 if (is_op && !is_fo)
2227 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2228 if (is_op && !is_fo)
2231 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2232 if (is_op && !is_fo)
2237 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2238 if (is_op && !is_fo)
2241 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2242 if (is_op && !is_fo)
2250 /* Server side command of CMODE. Changes channel mode */
2252 SILC_SERVER_CMD_FUNC(cmode)
2254 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2255 SilcServer server = cmd->server;
2256 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2257 SilcChannelID *channel_id;
2258 SilcChannelEntry channel;
2259 SilcChannelClientEntry chl;
2260 SilcBuffer packet, cidp;
2261 unsigned char *tmp, *tmp_id, *tmp_mask;
2262 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2264 SILC_LOG_DEBUG(("Start"));
2266 argc = silc_argument_get_arg_num(cmd->args);
2268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2269 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2274 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2278 /* Get Channel ID */
2279 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2282 SILC_STATUS_ERR_NO_CHANNEL_ID);
2285 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2288 SILC_STATUS_ERR_NO_CHANNEL_ID);
2292 /* Get the channel mode mask */
2293 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2296 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2299 SILC_GET32_MSB(mode_mask, tmp_mask);
2301 /* Get channel entry */
2302 channel = silc_idlist_find_channel_by_id(server->local_list,
2305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2306 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2310 /* Check whether this client is on the channel */
2311 if (!silc_server_client_on_channel(client, channel)) {
2312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2313 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2317 /* Get entry to the channel user list */
2318 silc_list_start(channel->user_list);
2319 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2320 if (chl->client == client)
2323 /* Check that client has rights to change any requested channel modes */
2324 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2326 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2331 * Check the modes. Modes that requires nothing special operation are
2335 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2336 /* Channel uses private keys to protect traffic. Client(s) has set the
2337 key locally they want to use, server does not know that key. */
2338 /* Nothing interesting to do here now */
2340 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2341 /* The mode is removed and we need to generate and distribute
2342 new channel key. Clients are not using private channel keys
2343 anymore after this. */
2345 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2348 /* Re-generate channel key */
2349 silc_server_create_channel_key(server, channel, 0);
2351 /* Encode channel key payload to be distributed on the channel */
2353 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2354 strlen(channel->channel_key->
2356 channel->channel_key->cipher->name,
2357 channel->key_len / 8, channel->key);
2359 /* If we are normal server then we will send it to our router. If we
2360 are router we will send it to all local servers that has clients on
2362 if (server->server_type == SILC_SERVER) {
2363 if (!server->standalone)
2364 silc_server_packet_send(server,
2365 cmd->server->router->connection,
2366 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2372 /* Send to locally connected clients on the channel */
2373 silc_server_packet_send_local_channel(server, channel,
2374 SILC_PACKET_CHANNEL_KEY, 0,
2375 packet->data, packet->len, FALSE);
2376 silc_buffer_free(packet);
2380 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2381 /* User limit is set on channel */
2382 unsigned int user_limit;
2384 /* Get user limit */
2385 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2387 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2389 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2393 SILC_GET32_MSB(user_limit, tmp);
2394 channel->mode_data.user_limit = user_limit;
2397 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2398 /* User limit mode is unset. Remove user limit */
2399 channel->mode_data.user_limit = 0;
2402 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2403 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2404 /* Passphrase has been set to channel */
2406 /* Get the passphrase */
2407 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2410 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2414 /* Save the passphrase */
2415 channel->mode_data.passphrase = strdup(tmp);
2418 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2419 /* Passphrase mode is unset. remove the passphrase */
2420 if (channel->mode_data.passphrase) {
2421 silc_free(channel->mode_data.passphrase);
2422 channel->mode_data.passphrase = NULL;
2427 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2428 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2429 /* Ban list is specified for channel */
2432 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2435 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2439 /* XXX check that channel founder is not banned */
2441 /* Save the ban list */
2442 channel->mode_data.ban_list = strdup(tmp);
2445 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2446 /* Ban mode is unset. Remove the entire ban list */
2447 if (channel->mode_data.ban_list) {
2448 silc_free(channel->mode_data.ban_list);
2449 channel->mode_data.ban_list = NULL;
2454 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2455 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2456 /* Invite list is specified for channel */
2458 /* Get invite list */
2459 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2461 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2462 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2466 /* Save the invite linst */
2467 channel->mode_data.invite_list = strdup(tmp);
2470 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2471 /* Invite list mode is unset. Remove the entire invite list */
2472 if (channel->mode_data.invite_list) {
2473 silc_free(channel->mode_data.invite_list);
2474 channel->mode_data.invite_list = NULL;
2479 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2480 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2481 /* Cipher to use protect the traffic */
2482 unsigned int key_len = 128;
2486 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2489 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2493 cp = strchr(tmp, ':');
2499 /* XXX Duplicated code, make own function for this!! */
2501 /* Delete old cipher and allocate the new one */
2502 silc_cipher_free(channel->channel_key);
2503 silc_cipher_alloc(tmp, &channel->channel_key);
2509 /* Re-generate channel key */
2510 silc_server_create_channel_key(server, channel, key_len);
2512 /* Encode channel key payload to be distributed on the channel */
2514 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2515 strlen(channel->channel_key->
2517 channel->channel_key->cipher->name,
2518 channel->key_len / 8, channel->key);
2520 /* If we are normal server then we will send it to our router. If we
2521 are router we will send it to all local servers that has clients on
2523 if (server->server_type == SILC_SERVER) {
2524 if (!server->standalone)
2525 silc_server_packet_send(server,
2526 cmd->server->router->connection,
2527 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2533 /* Send to locally connected clients on the channel */
2534 silc_server_packet_send_local_channel(server, channel,
2535 SILC_PACKET_CHANNEL_KEY, 0,
2536 packet->data, packet->len, FALSE);
2537 silc_buffer_free(packet);
2540 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2541 /* Cipher mode is unset. Remove the cipher and revert back to
2544 if (channel->mode_data.cipher) {
2545 silc_free(channel->mode_data.cipher);
2546 channel->mode_data.cipher = NULL;
2547 channel->mode_data.key_len = 0;
2550 /* Generate new cipher and key for the channel */
2552 /* XXX Duplicated code, make own function for this!! */
2554 /* Delete old cipher and allocate default one */
2555 silc_cipher_free(channel->channel_key);
2556 if (!channel->cipher)
2557 silc_cipher_alloc("twofish", &channel->channel_key);
2559 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2561 /* Re-generate channel key */
2562 silc_server_create_channel_key(server, channel, 0);
2564 /* Encode channel key payload to be distributed on the channel */
2566 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2567 strlen(channel->channel_key->
2569 channel->channel_key->cipher->name,
2570 channel->key_len / 8, channel->key);
2572 /* If we are normal server then we will send it to our router. If we
2573 are router we will send it to all local servers that has clients on
2575 if (server->server_type == SILC_SERVER) {
2576 if (!server->standalone)
2577 silc_server_packet_send(server,
2578 cmd->server->router->connection,
2579 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2585 /* Send to locally connected clients on the channel */
2586 silc_server_packet_send_local_channel(server, channel,
2587 SILC_PACKET_CHANNEL_KEY, 0,
2588 packet->data, packet->len, FALSE);
2589 silc_buffer_free(packet);
2593 /* Finally, set the mode */
2594 channel->mode = mode_mask;
2596 /* Send CMODE_CHANGE notify */
2597 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2598 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2599 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2600 cidp->data, cidp->len,
2603 /* Set CMODE notify type to network */
2604 if (!server->standalone)
2605 silc_server_send_notify_cmode(server, server->router->connection,
2606 server->server_type == SILC_ROUTER ?
2607 TRUE : FALSE, channel,
2608 mode_mask, client->id, SILC_ID_CLIENT_LEN);
2610 /* Send command reply to sender */
2611 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2612 SILC_STATUS_OK, 0, 1,
2614 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2615 packet->data, packet->len, FALSE);
2617 silc_buffer_free(packet);
2618 silc_free(channel_id);
2622 silc_server_command_free(cmd);
2625 /* Server side of CUMODE command. Changes client's mode on a channel. */
2627 SILC_SERVER_CMD_FUNC(cumode)
2629 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2630 SilcServer server = cmd->server;
2631 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2632 SilcChannelID *channel_id;
2633 SilcClientID *client_id;
2634 SilcChannelEntry channel;
2635 SilcClientEntry target_client;
2636 SilcChannelClientEntry chl;
2637 SilcBuffer packet, idp;
2638 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2639 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
2642 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2644 /* Get Channel ID */
2645 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2647 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2648 SILC_STATUS_ERR_NO_CHANNEL_ID);
2651 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
2653 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2654 SILC_STATUS_ERR_NO_CHANNEL_ID);
2658 /* Get channel entry */
2659 channel = silc_idlist_find_channel_by_id(server->local_list,
2662 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2663 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2667 /* Check whether sender is on the channel */
2668 if (!silc_server_client_on_channel(client, channel)) {
2669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2670 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2674 /* Check that client has rights to change other's rights */
2675 silc_list_start(channel->user_list);
2676 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2677 if (chl->client == client) {
2678 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2679 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2681 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2685 sender_mask = chl->mode;
2690 /* Get the target client's channel mode mask */
2691 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2693 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2694 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2697 SILC_GET32_MSB(target_mask, tmp_mask);
2699 /* Get target Client ID */
2700 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2702 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2703 SILC_STATUS_ERR_NO_CHANNEL_ID);
2706 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2708 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2709 SILC_STATUS_ERR_NO_CHANNEL_ID);
2713 /* Get target client's entry */
2714 target_client = silc_idlist_find_client_by_id(server->local_list,
2716 if (!target_client) {
2717 target_client = silc_idlist_find_client_by_id(server->global_list,
2721 /* Check whether target client is on the channel */
2722 if (!silc_server_client_on_channel(target_client, channel)) {
2723 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2724 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2728 /* Get entry to the channel user list */
2729 silc_list_start(channel->user_list);
2730 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2731 if (chl->client == target_client)
2738 /* If the target client is founder, no one else can change their mode
2740 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2741 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2742 SILC_STATUS_ERR_NOT_YOU);
2746 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2747 /* Cannot promote anyone to channel founder */
2748 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2749 SILC_STATUS_ERR_NOT_YOU);
2752 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2753 if (target_client == client) {
2754 /* Remove channel founder rights from itself */
2755 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2758 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2759 SILC_STATUS_ERR_NOT_YOU);
2765 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2766 /* Promote to operator */
2767 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2768 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2772 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2773 /* Demote to normal user */
2774 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2779 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2781 /* Send notify to channel, notify only if mode was actually changed. */
2783 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2784 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2785 idp->data, idp->len,
2789 /* Set CUMODE notify type to network */
2790 if (!server->standalone)
2791 silc_server_send_notify_cumode(server, server->router->connection,
2792 server->server_type == SILC_ROUTER ?
2793 TRUE : FALSE, channel,
2794 target_mask, client->id,
2797 SILC_ID_CLIENT_LEN);
2800 /* Send command reply to sender */
2801 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2802 SILC_STATUS_OK, 0, 2,
2804 3, tmp_id, tmp_len);
2805 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2806 packet->data, packet->len, FALSE);
2808 silc_buffer_free(packet);
2809 silc_free(channel_id);
2810 silc_free(client_id);
2811 silc_buffer_free(idp);
2814 silc_server_command_free(cmd);
2817 /* Server side of KICK command. Kicks client out of channel. */
2819 SILC_SERVER_CMD_FUNC(kick)
2823 SILC_SERVER_CMD_FUNC(restart)
2827 SILC_SERVER_CMD_FUNC(close)
2831 SILC_SERVER_CMD_FUNC(die)
2835 SILC_SERVER_CMD_FUNC(silcoper)
2839 /* Server side command of LEAVE. Removes client from a channel. */
2841 SILC_SERVER_CMD_FUNC(leave)
2843 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2844 SilcServer server = cmd->server;
2845 SilcSocketConnection sock = cmd->sock;
2846 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2848 SilcChannelEntry channel;
2850 unsigned int i, len;
2853 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2855 /* Get Channel ID */
2856 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2858 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2859 SILC_STATUS_ERR_NO_CHANNEL_ID);
2862 id = silc_id_payload_parse_id(tmp, len);
2864 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2865 SILC_STATUS_ERR_NO_CHANNEL_ID);
2869 /* Get channel entry */
2870 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2872 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2873 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2877 /* Check whether this client is on the channel */
2878 if (!silc_server_client_on_channel(id_entry, channel)) {
2879 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2880 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2884 /* Notify routers that they should remove this client from their list
2885 of clients on the channel. Send LEAVE notify type. */
2886 if (!server->standalone)
2887 silc_server_send_notify_leave(server, server->router->connection,
2888 server->server_type == SILC_ROUTER ?
2889 TRUE : FALSE, channel, id_entry->id,
2890 SILC_ID_CLIENT_LEN);
2892 /* Remove client from channel */
2893 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2895 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2898 /* If the channel does not exist anymore we won't send anything */
2902 /* Re-generate channel key */
2903 silc_server_create_channel_key(server, channel, 0);
2905 /* Encode channel key payload to be distributed on the channel */
2907 silc_channel_key_payload_encode(len, tmp,
2908 strlen(channel->channel_key->cipher->name),
2909 channel->channel_key->cipher->name,
2910 channel->key_len / 8, channel->key);
2912 /* If we are normal server then we will send it to our router. If we
2913 are router we will send it to all local servers that has clients on
2915 if (server->server_type == SILC_SERVER) {
2916 if (!server->standalone)
2917 silc_server_packet_send(server,
2918 cmd->server->router->connection,
2919 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2920 packet->len, FALSE);
2925 /* Send to locally connected clients on the channel */
2926 silc_server_packet_send_local_channel(server, channel,
2927 SILC_PACKET_CHANNEL_KEY, 0,
2928 packet->data, packet->len, FALSE);
2930 silc_buffer_free(packet);
2934 silc_server_command_free(cmd);
2937 /* Server side of command USERS. Resolves clients and their USERS currently
2938 joined on the requested channel. The list of Client ID's and their modes
2939 on the channel is sent back. */
2941 SILC_SERVER_CMD_FUNC(users)
2943 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2944 SilcServer server = cmd->server;
2945 SilcChannelEntry channel;
2946 SilcChannelClientEntry chl;
2949 unsigned char *channel_id;
2950 unsigned int channel_id_len;
2951 SilcBuffer client_id_list;
2952 SilcBuffer client_mode_list;
2954 unsigned char lc[4];
2955 unsigned int list_count = 0;
2956 unsigned short ident = silc_command_get_ident(cmd->payload);
2958 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
2960 /* Get Channel ID */
2961 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
2963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2964 SILC_STATUS_ERR_NO_CHANNEL_ID);
2967 id = silc_id_payload_parse_id(channel_id, channel_id_len);
2969 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2970 SILC_STATUS_ERR_NO_CHANNEL_ID);
2974 /* If we are server and we don't know about this channel we will send
2975 the command to our router. If we know about the channel then we also
2976 have the list of users already. */
2977 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2979 if (server->server_type == SILC_SERVER && !server->standalone &&
2983 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2984 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2986 /* Send USERS command */
2987 silc_server_packet_send(server, server->router->connection,
2988 SILC_PACKET_COMMAND, cmd->packet->flags,
2989 tmpbuf->data, tmpbuf->len, TRUE);
2991 /* Reprocess this packet after received reply */
2992 silc_server_command_pending(server, SILC_COMMAND_USERS,
2993 silc_command_get_ident(cmd->payload),
2994 silc_server_command_destructor,
2995 silc_server_command_users,
2996 silc_server_command_dup(cmd));
2997 cmd->pending = TRUE;
2998 silc_command_set_ident(cmd->payload, ident);
3000 silc_buffer_free(tmpbuf);
3005 /* We are router and we will check the global list as well. */
3006 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3008 /* Channel really does not exist */
3009 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3010 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3015 /* Assemble the lists now */
3017 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
3018 silc_list_count(channel->user_list));
3019 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
3021 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
3022 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
3024 silc_list_start(channel->user_list);
3025 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3027 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
3028 silc_buffer_put(client_id_list, idp->data, idp->len);
3029 silc_buffer_pull(client_id_list, idp->len);
3030 silc_buffer_free(idp);
3032 /* Client's mode on channel */
3033 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
3034 silc_buffer_pull(client_mode_list, 4);
3038 silc_buffer_push(client_id_list,
3039 client_id_list->data - client_id_list->head);
3040 silc_buffer_push(client_mode_list,
3041 client_mode_list->data - client_mode_list->head);
3044 SILC_PUT32_MSB(list_count, lc);
3047 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3048 SILC_STATUS_OK, 0, 4,
3049 2, channel_id, channel_id_len,
3051 4, client_id_list->data,
3052 client_id_list->len,
3053 5, client_mode_list->data,
3054 client_mode_list->len);
3055 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3056 packet->data, packet->len, FALSE);
3058 silc_buffer_free(packet);
3059 silc_buffer_free(client_id_list);
3060 silc_buffer_free(client_mode_list);
3064 silc_server_command_free(cmd);