5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 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 static void silc_server_command_free(SilcServerCommandContext cmd);
41 void silc_server_command_send_names(SilcServer server,
42 SilcSocketConnection sock,
43 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(names, NAMES, SILC_CF_LAG | SILC_CF_REG),
81 /* Returns TRUE if the connection is registered. Unregistered connections
82 usually cannot send commands hence the check. */
84 static int silc_server_is_registered(SilcServer server,
85 SilcSocketConnection sock,
86 SilcServerCommandContext cmd,
89 SilcIDListData idata = (SilcIDListData)sock->user_data;
90 if (idata->registered)
93 silc_server_command_send_status_reply(cmd, command,
94 SILC_STATUS_ERR_NOT_REGISTERED);
95 silc_server_command_free(cmd);
99 /* Processes received command packet. */
101 void silc_server_command_process(SilcServer server,
102 SilcSocketConnection sock,
103 SilcPacketContext *packet)
105 SilcServerCommandContext ctx;
106 SilcServerCommand *cmd;
109 /* XXX allow commands in but do not execute them more than once per
112 /* Check whether it is allowed for this connection to execute any
114 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
116 SilcClientEntry client = (SilcClientEntry)sock->user_data;
121 /* Allow only one command executed in 2 seconds. */
122 curtime = time(NULL);
123 if (client->last_command && (curtime - client->last_command) < 2)
126 /* Update access time */
127 client->last_command = curtime;
131 /* Allocate command context. This must be free'd by the
132 command routine receiving it. */
133 ctx = silc_calloc(1, sizeof(*ctx));
134 ctx->server = server;
136 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
138 /* Parse the command payload in the packet */
139 ctx->payload = silc_command_payload_parse(packet->buffer);
141 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
142 silc_buffer_free(packet->buffer);
143 silc_packet_context_free(packet);
147 ctx->args = silc_command_get_args(ctx->payload);
149 /* Execute command. If this fails the packet is dropped. */
150 for (cmd = silc_command_list; cmd->cb; cmd++)
151 if (cmd->cmd == silc_command_get(ctx->payload)) {
153 if (!(cmd->flags & SILC_CF_REG)) {
158 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
165 SILC_LOG_ERROR(("Unknown command, packet dropped"));
166 silc_server_command_free(ctx);
171 /* Add new pending command to be executed when reply to a command has been
172 received. The `reply_cmd' is the command that will call the `callback'
173 with `context' when reply has been received. If `ident' is non-zero
174 the `callback' will be executed when received reply with command
175 identifier `ident'. */
177 void silc_server_command_pending(SilcServer server,
178 SilcCommand reply_cmd,
179 unsigned short ident,
180 SilcCommandCb callback,
183 SilcServerCommandPending *reply;
185 reply = silc_calloc(1, sizeof(*reply));
186 reply->reply_cmd = reply_cmd;
187 reply->ident = ident;
188 reply->context = context;
189 reply->callback = callback;
190 silc_dlist_add(server->pending_commands, reply);
193 /* Deletes pending command by reply command type. */
195 void silc_server_command_pending_del(SilcServer server,
196 SilcCommand reply_cmd,
197 unsigned short ident)
199 SilcServerCommandPending *r;
201 silc_dlist_start(server->pending_commands);
202 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
203 if (r->reply_cmd == reply_cmd && r->ident == ident) {
204 silc_dlist_del(server->pending_commands, r);
210 /* Checks for pending commands and marks callbacks to be called from
211 the command reply function. Returns TRUE if there were pending command. */
213 int silc_server_command_pending_check(SilcServer server,
214 SilcServerCommandReplyContext ctx,
216 unsigned short ident)
218 SilcServerCommandPending *r;
220 silc_dlist_start(server->pending_commands);
221 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
222 if (r->reply_cmd == command && r->ident == ident) {
223 ctx->context = r->context;
224 ctx->callback = r->callback;
233 /* Free's the command context allocated before executing the command */
235 static void silc_server_command_free(SilcServerCommandContext cmd)
239 silc_command_free_payload(cmd->payload);
241 silc_packet_context_free(cmd->packet);
246 /* Sends simple status message as command reply packet */
249 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
251 SilcCommandStatus status)
255 SILC_LOG_DEBUG(("Sending command status %d", status));
257 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
258 silc_server_packet_send(cmd->server, cmd->sock,
259 SILC_PACKET_COMMAND_REPLY, 0,
260 buffer->data, buffer->len, FALSE);
261 silc_buffer_free(buffer);
264 /* Sends command status reply with one extra argument. The argument
265 type must be sent as argument. */
268 silc_server_command_send_status_data(SilcServerCommandContext cmd,
270 SilcCommandStatus status,
271 unsigned int arg_type,
273 unsigned int arg_len)
277 SILC_LOG_DEBUG(("Sending command status %d", status));
279 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
280 arg_type, arg, arg_len);
281 silc_server_packet_send(cmd->server, cmd->sock,
282 SILC_PACKET_COMMAND_REPLY, 0,
283 buffer->data, buffer->len, FALSE);
284 silc_buffer_free(buffer);
287 /* Server side of command WHOIS. Processes user's query and sends found
288 results as command replies back to the client. */
290 SILC_SERVER_CMD_FUNC(whois)
292 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
293 SilcServer server = cmd->server;
294 char *tmp, *nick = NULL, *server_name = NULL;
295 unsigned int i, argc, count = 0, len, clients_count;
297 SilcClientID *client_id = NULL;
298 SilcBuffer packet, idp;
299 SilcClientEntry *clients = NULL, entry;
300 SilcCommandStatus status;
302 SILC_LOG_DEBUG(("Start"));
304 argc = silc_argument_get_arg_num(cmd->args);
306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
307 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
312 SILC_STATUS_ERR_TOO_MANY_PARAMS);
316 /* If client ID is in the command it must be used instead of nickname */
317 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
320 /* No ID, get the nickname@server string and parse it. */
321 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
323 if (strchr(tmp, '@')) {
324 len = strcspn(tmp, "@");
325 nick = silc_calloc(len + 1, sizeof(char));
326 memcpy(nick, tmp, len);
327 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
328 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
334 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
338 /* Command includes ID, use that */
339 client_id = silc_id_payload_parse_id(tmp, len);
343 /* Get the max count of reply messages allowed */
345 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
348 SILC_STATUS_ERR_TOO_MANY_PARAMS);
352 silc_free(server_name);
358 /* Protocol dictates that we must always send the received WHOIS request
359 to our router if we are normal server, so let's do it now unless we
360 are standalone. We will not send any replies to the client until we
361 have received reply from the router. */
362 if (!server->standalone) {
365 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
366 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
368 /* Send WHOIS command to our router */
369 silc_server_packet_send(server, (SilcSocketConnection)
370 server->router->connection,
371 SILC_PACKET_COMMAND, cmd->packet->flags,
372 tmpbuf->data, tmpbuf->len, TRUE);
375 /* We are standalone, let's just do local search and send reply to
376 requesting client. */
378 /* Get all clients matching that nickname */
380 clients = silc_idlist_get_clients_by_nickname(server->local_list,
384 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
386 clients = silc_calloc(1, sizeof(*clients));
392 /* If we are router then we will check our global list as well. */
393 if (server->server_type == SILC_ROUTER) {
395 silc_idlist_find_client_by_nickname(server->global_list,
398 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
399 SILC_STATUS_ERR_NO_SUCH_NICK,
400 3, tmp, strlen(tmp));
407 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
408 SILC_STATUS_ERR_NO_SUCH_NICK,
409 3, tmp, strlen(tmp));
414 /* We are standalone and will send reply to client */
417 status = SILC_STATUS_OK;
418 if (clients_count > 1)
419 status = SILC_STATUS_LIST_START;
421 for (i = 0; i < clients_count; i++) {
424 if (count && i - 1 == count)
427 if (clients_count > 2)
428 status = SILC_STATUS_LIST_ITEM;
430 if (clients_count > 1 && i == clients_count - 1)
431 status = SILC_STATUS_LIST_END;
433 /* Send WHOIS reply */
434 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
435 tmp = silc_argument_get_first_arg(cmd->args, NULL);
438 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
439 char nh[256], uh[256];
440 unsigned char idle[4];
441 SilcSocketConnection hsock;
443 memset(uh, 0, sizeof(uh));
444 memset(nh, 0, sizeof(nh));
446 strncat(nh, entry->nickname, strlen(entry->nickname));
448 len = entry->router ? strlen(entry->router->server_name) :
449 strlen(server->server_name);
450 strncat(nh, entry->router ? entry->router->server_name :
451 server->server_name, len);
453 strncat(uh, entry->username, strlen(entry->username));
455 hsock = (SilcSocketConnection)entry->connection;
456 len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
457 strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
459 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
464 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
466 2, idp->data, idp->len,
470 strlen(entry->userinfo),
474 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
476 2, idp->data, idp->len,
484 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
486 2, idp->data, idp->len,
488 strlen(entry->nickname),
489 4, tmp, strlen(tmp)); /* XXX */
491 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
492 0, packet->data, packet->len, FALSE);
494 silc_buffer_free(packet);
495 silc_buffer_free(idp);
501 silc_free(client_id);
504 silc_server_command_free(cmd);
507 SILC_SERVER_CMD_FUNC(whowas)
511 SILC_SERVER_CMD_FUNC(identify)
513 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
514 SilcServer server = cmd->server;
515 char *tmp, *nick = NULL, *server_name = NULL;
516 unsigned int argc, count = 0, len;
518 SilcClientID *client_id = NULL;
519 SilcClientEntry entry;
520 SilcBuffer packet, idp;
522 SILC_LOG_DEBUG(("Start"));
524 argc = silc_argument_get_arg_num(cmd->args);
526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
527 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
532 SILC_STATUS_ERR_TOO_MANY_PARAMS);
536 /* If client ID is in the command it must be used instead of nickname */
537 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
540 /* Get the nickname@server string and parse it. */
541 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
543 if (strchr(tmp, '@')) {
544 len = strcspn(tmp, "@");
545 nick = silc_calloc(len + 1, sizeof(char));
546 memcpy(nick, tmp, len);
547 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
548 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
553 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
554 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
558 /* Command includes ID, use that */
559 client_id = silc_id_payload_parse_id(tmp, len);
563 /* Get the max count of reply messages allowed */
565 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
567 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
568 SILC_STATUS_ERR_TOO_MANY_PARAMS);
576 entry = silc_idlist_find_client_by_nickname(server->local_list,
579 entry = silc_idlist_find_client_by_hash(server->global_list,
580 nick, server->md5hash);
582 entry = silc_idlist_find_client_by_id(server->local_list, client_id);
585 /* If client was not found and if we are normal server and are connected
586 to a router we will make global query from the router. */
587 if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
589 SilcBuffer buffer = cmd->packet->buffer;
591 SILC_LOG_DEBUG(("Requesting identify from router"));
593 /* Send IDENTIFY command to our router */
594 silc_buffer_push(buffer, buffer->data - buffer->head);
595 silc_server_packet_forward(server, (SilcSocketConnection)
596 server->router->connection,
597 buffer->data, buffer->len, TRUE);
601 /* If we are router we have checked our local list by nickname and our
602 global list by hash so far. It is possible that the client is still not
603 found and we'll check it from local list by hash. */
604 if (!entry && server->server_type == SILC_ROUTER)
605 entry = silc_idlist_find_client_by_hash(server->local_list,
606 nick, server->md5hash);
609 /* The client definitely does not exist */
610 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
611 SILC_STATUS_ERR_NO_SUCH_NICK,
612 3, tmp, strlen(tmp));
616 /* Send IDENTIFY reply */
617 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
618 tmp = silc_argument_get_first_arg(cmd->args, NULL);
619 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
620 SILC_STATUS_OK, 0, 2,
621 2, idp->data, idp->len,
622 3, nick, strlen(nick));
623 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
624 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
625 silc_server_packet_send_dest(server, cmd->sock,
626 SILC_PACKET_COMMAND_REPLY, 0,
627 id, cmd->packet->src_id_type,
628 packet->data, packet->len, FALSE);
631 silc_server_packet_send(server, cmd->sock,
632 SILC_PACKET_COMMAND_REPLY, 0,
633 packet->data, packet->len, FALSE);
636 silc_buffer_free(packet);
637 silc_buffer_free(idp);
639 silc_free(client_id);
645 silc_free(server_name);
646 silc_server_command_free(cmd);
649 /* Checks string for bad characters and returns TRUE if they are found. */
651 static int silc_server_command_bad_chars(char *nick)
653 if (strchr(nick, '\\')) return TRUE;
654 if (strchr(nick, '\"')) return TRUE;
655 if (strchr(nick, '´')) return TRUE;
656 if (strchr(nick, '`')) return TRUE;
657 if (strchr(nick, '\'')) return TRUE;
658 if (strchr(nick, '*')) return TRUE;
659 if (strchr(nick, '/')) return TRUE;
660 if (strchr(nick, '@')) return TRUE;
665 /* Server side of command NICK. Sets nickname for user. Setting
666 nickname causes generation of a new client ID for the client. The
667 new client ID is sent to the client after changing the nickname. */
669 SILC_SERVER_CMD_FUNC(nick)
671 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
672 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
673 SilcServer server = cmd->server;
674 SilcBuffer packet, nidp, oidp;
675 SilcClientID *new_id;
678 SILC_LOG_DEBUG(("Start"));
680 /* Check number of arguments */
681 if (silc_argument_get_arg_num(cmd->args) < 1) {
682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
683 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
688 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
689 if (silc_server_command_bad_chars(nick) == TRUE) {
690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
691 SILC_STATUS_ERR_BAD_NICKNAME);
695 /* Create new Client ID */
696 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
697 cmd->server->md5hash, nick,
700 /* Send notify about nickname change to our router. We send the new
701 ID and ask to replace it with the old one. If we are router the
702 packet is broadcasted. */
703 if (!cmd->server->standalone)
704 silc_server_send_replace_id(server, server->router->connection,
705 server->server_type == SILC_SERVER ?
706 FALSE : TRUE, client->id,
707 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
708 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
710 /* Remove old cache entry */
711 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
714 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
718 memset(client->id, 0, SILC_ID_CLIENT_LEN);
719 silc_free(client->id);
722 /* Save the nickname as this client is our local client */
723 if (client->nickname)
724 silc_free(client->nickname);
726 client->nickname = strdup(nick);
729 /* Update client cache */
730 silc_idcache_add(server->local_list->clients, client->nickname,
731 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
733 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
735 /* Send NICK_CHANGE notify */
736 silc_server_send_notify_on_channels(server, client,
737 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
738 oidp->data, oidp->len,
739 nidp->data, nidp->len);
741 /* Send the new Client ID as reply command back to client */
742 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
743 SILC_STATUS_OK, 0, 1,
744 2, nidp->data, nidp->len);
745 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
746 0, packet->data, packet->len, FALSE);
748 silc_buffer_free(packet);
749 silc_buffer_free(nidp);
750 silc_buffer_free(oidp);
753 silc_server_command_free(cmd);
756 SILC_SERVER_CMD_FUNC(list)
760 /* Server side of TOPIC command. Sets topic for channel and/or returns
761 current topic to client. */
763 SILC_SERVER_CMD_FUNC(topic)
765 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
766 SilcServer server = cmd->server;
767 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
768 SilcChannelID *channel_id;
769 SilcChannelEntry channel;
770 SilcChannelClientEntry chl;
771 SilcBuffer packet, idp;
773 unsigned int argc, tmp_len;
775 /* Check number of arguments */
776 argc = silc_argument_get_arg_num(cmd->args);
778 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
779 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
784 SILC_STATUS_ERR_TOO_MANY_PARAMS);
789 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
791 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
792 SILC_STATUS_ERR_NO_CHANNEL_ID);
795 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
797 /* Check whether the channel exists */
798 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
801 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
807 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
810 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
814 if (strlen(tmp) > 256) {
815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
816 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
820 /* See whether has rights to change topic */
821 silc_list_start(channel->user_list);
822 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
823 if (chl->client == client) {
824 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
825 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
826 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
834 /* Set the topic for channel */
836 silc_free(channel->topic);
837 channel->topic = strdup(tmp);
839 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
841 /* Send notify about topic change to all clients on the channel */
842 silc_server_send_notify_to_channel(server, channel, TRUE,
843 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
845 channel->topic, strlen(channel->topic));
846 silc_buffer_free(idp);
849 /* Send the topic to client as reply packet */
850 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
852 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
853 SILC_STATUS_OK, 0, 2,
854 2, idp->data, idp->len,
856 strlen(channel->topic));
858 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
859 SILC_STATUS_OK, 0, 1,
860 2, idp->data, idp->len);
861 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
862 0, packet->data, packet->len, FALSE);
864 silc_buffer_free(packet);
865 silc_buffer_free(idp);
866 silc_free(channel_id);
869 silc_server_command_free(cmd);
872 /* Server side of INVITE command. Invites some client to join some channel. */
874 SILC_SERVER_CMD_FUNC(invite)
876 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
877 SilcServer server = cmd->server;
878 SilcSocketConnection sock = cmd->sock, dest_sock;
879 SilcClientEntry sender, dest;
880 SilcClientID *dest_id;
881 SilcChannelEntry channel;
882 SilcChannelID *channel_id;
885 unsigned int argc, len;
887 /* Check number of arguments */
888 argc = silc_argument_get_arg_num(cmd->args);
890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
891 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
895 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
896 SILC_STATUS_ERR_TOO_MANY_PARAMS);
900 /* Get destination ID */
901 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
904 SILC_STATUS_ERR_NO_CLIENT_ID);
907 dest_id = silc_id_payload_parse_id(tmp, len);
910 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
912 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
913 SILC_STATUS_ERR_NO_CHANNEL_ID);
916 channel_id = silc_id_payload_parse_id(tmp, len);
918 /* Check whether the channel exists */
919 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
921 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
922 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
926 /* Check whether the sender of this command is on the channel. */
927 sender = (SilcClientEntry)sock->user_data;
928 if (!silc_server_client_on_channel(sender, channel)) {
929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
930 SILC_STATUS_ERR_NOT_ON_CHANNEL);
934 /* Check whether the channel is invite-only channel. If yes then the
935 sender of this command must be at least channel operator. */
936 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
937 SilcChannelClientEntry chl;
939 silc_list_start(channel->user_list);
940 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
941 if (chl->client == sender) {
942 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
944 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
951 /* Find the connection data for the destination. If it is local we will
952 send it directly otherwise we will send it to router for routing. */
953 dest = silc_idlist_find_client_by_id(server->local_list, dest_id);
955 dest_sock = (SilcSocketConnection)dest->connection;
957 dest_sock = silc_server_get_route(server, dest_id, SILC_ID_CLIENT);
959 /* Check whether the requested client is already on the channel. */
960 /* XXX if we are normal server we don't know about global clients on
961 the channel thus we must request it (NAMES command), check from
962 local cache as well. */
963 if (silc_server_client_on_channel(dest, channel)) {
964 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
965 SILC_STATUS_ERR_USER_ON_CHANNEL);
969 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
971 /* Send notify to the client that is invited to the channel */
972 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
973 SILC_NOTIFY_TYPE_INVITE, 2,
974 sidp->data, sidp->len, tmp, len);
976 /* Send command reply */
977 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
980 silc_buffer_free(sidp);
983 silc_server_command_free(cmd);
986 /* Quits connection to client. This gets called if client won't
987 close the connection even when it has issued QUIT command. */
989 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
991 SilcServer server = (SilcServer)context;
992 SilcSocketConnection sock = server->sockets[fd];
994 /* Free all client specific data, such as client entry and entires
995 on channels this client may be on. */
996 silc_server_free_sock_user_data(server, sock);
998 /* Close the connection on our side */
999 silc_server_close_connection(server, sock);
1002 /* Quits SILC session. This is the normal way to disconnect client. */
1004 SILC_SERVER_CMD_FUNC(quit)
1006 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1007 SilcServer server = cmd->server;
1008 SilcSocketConnection sock = cmd->sock;
1010 SILC_LOG_DEBUG(("Start"));
1012 /* We quit the connection with little timeout */
1013 silc_task_register(server->timeout_queue, sock->sock,
1014 silc_server_command_quit_cb, server,
1015 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1017 silc_server_command_free(cmd);
1020 SILC_SERVER_CMD_FUNC(kill)
1024 /* Server side of command INFO. This sends information about us to
1025 the client. If client requested specific server we will send the
1026 command to that server. */
1028 SILC_SERVER_CMD_FUNC(info)
1030 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1031 SilcServer server = cmd->server;
1032 SilcBuffer packet, idp;
1034 char info_string[256], *dest_server;
1036 argc = silc_argument_get_arg_num(cmd->args);
1038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1039 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1044 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1048 /* Get server name */
1049 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1052 SILC_STATUS_ERR_NO_SUCH_SERVER);
1056 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1057 /* Send our reply */
1058 memset(info_string, 0, sizeof(info_string));
1059 snprintf(info_string, sizeof(info_string),
1060 "location: %s server: %s admin: %s <%s>",
1061 server->config->admin_info->location,
1062 server->config->admin_info->server_type,
1063 server->config->admin_info->admin_name,
1064 server->config->admin_info->admin_email);
1066 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1068 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1069 SILC_STATUS_OK, 0, 2,
1070 2, idp->data, idp->len,
1072 strlen(info_string));
1073 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1074 packet->data, packet->len, FALSE);
1076 silc_buffer_free(packet);
1077 silc_buffer_free(idp);
1079 /* Send this command to the requested server */
1081 if (server->server_type == SILC_SERVER && !server->standalone) {
1085 if (server->server_type == SILC_ROUTER) {
1091 silc_server_command_free(cmd);
1094 SILC_SERVER_CMD_FUNC(connect)
1098 /* Server side of command PING. This just replies to the ping. */
1100 SILC_SERVER_CMD_FUNC(ping)
1102 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1103 SilcServer server = cmd->server;
1105 unsigned int argc, len;
1108 argc = silc_argument_get_arg_num(cmd->args);
1110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1111 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1116 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1121 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1123 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1124 SILC_STATUS_ERR_NO_SERVER_ID);
1127 id = silc_id_str2id(tmp, SILC_ID_SERVER);
1131 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1132 /* Send our reply */
1133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1137 SILC_STATUS_ERR_NO_SUCH_SERVER);
1144 silc_server_command_free(cmd);
1147 SILC_SERVER_CMD_FUNC(oper)
1156 SilcChannelEntry channel;
1158 SilcClientEntry client;
1159 } JoinInternalContext;
1161 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1163 JoinInternalContext *ctx = (JoinInternalContext *)context;
1165 if (ctx->channel->key && ctx->channel->key_len) {
1168 clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1170 silc_server_send_notify_to_channel(ctx->server, ctx->channel, FALSE,
1171 SILC_NOTIFY_TYPE_JOIN, 1,
1172 clidp->data, clidp->len);
1174 /* Send NEW_CHANNEL_USER packet to primary route */
1175 silc_server_send_new_channel_user(server, server->router->connection,
1176 server->server_type == SILC_SERVER ?
1178 channel->id, SILC_ID_CHANNEL_LEN,
1179 client->id, SILC_ID_CLIENT_LEN);
1182 /* Send NAMES command reply to the joined channel so the user sees who
1183 is currently on the channel. */
1184 silc_server_command_send_names(ctx->server, ctx->client->connection,
1187 silc_buffer_free(clidp);
1190 silc_task_register(ctx->server->timeout_queue, fd,
1191 silc_server_command_join_notify, context,
1192 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1196 /* Assembles NAMES command and executes it. This is called when client
1197 joins to a channel and we wan't to send NAMES command reply to the
1200 void silc_server_command_send_names(SilcServer server,
1201 SilcSocketConnection sock,
1202 SilcChannelEntry channel)
1204 SilcServerCommandContext cmd;
1205 SilcBuffer buffer, idp;
1207 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1208 buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1209 1, idp->data, idp->len);
1211 cmd = silc_calloc(1, sizeof(*cmd));
1212 cmd->payload = silc_command_payload_parse(buffer);
1213 cmd->args = silc_command_get_args(cmd->payload);
1214 cmd->server = server;
1216 cmd->pending = FALSE;
1218 silc_server_command_names((void *)cmd);
1223 /* Internal routine to join channel. The channel sent to this function
1224 has been either created or resolved from ID lists. This joins the sent
1225 client to the channel. */
1227 static void silc_server_command_join_channel(SilcServer server,
1228 SilcServerCommandContext cmd,
1229 SilcChannelEntry channel,
1233 SilcSocketConnection sock = cmd->sock;
1235 unsigned int tmp_len;
1236 unsigned char *passphrase = NULL, mode[4];
1237 SilcClientEntry client;
1238 SilcChannelClientEntry chl;
1239 SilcBuffer reply, chidp, clidp;
1244 /* Get passphrase */
1245 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1247 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1248 memcpy(passphrase, tmp, tmp_len);
1252 * Check channel modes
1255 /* Check invite list if channel is invite-only channel */
1256 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1257 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1258 /* Invite list is specified. Check whether client is invited in the
1259 list. If not, then check whether it has been invited otherwise. */
1262 /* XXX client must be invited to be able to join the channel */
1266 /* Check ban list if set */
1267 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1271 /* Check the channel passphrase if set. */
1272 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1273 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1274 strlen(channel->mode_data.passphrase))) {
1275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1276 SILC_STATUS_ERR_BAD_PASSWORD);
1281 /* Check user count limit if set. */
1282 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1283 if (silc_list_count(channel->user_list) + 1 >
1284 channel->mode_data.user_limit) {
1285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1286 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1292 * Client is allowed to join to the channel. Make it happen.
1295 /* If the JOIN request was forwarded to us we will make a bit slower
1296 query to get the client pointer. Otherwise, we get the client pointer
1298 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1299 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1300 client = silc_idlist_find_client_by_id(server->local_list, id);
1303 SILC_LOG_ERROR(("Forwarded join command did not find the client who "
1304 "wanted to join the channel"));
1309 client = (SilcClientEntry)sock->user_data;
1312 /* Check whether the client already is on the channel */
1313 if (silc_server_client_on_channel(client, channel)) {
1314 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1315 SILC_STATUS_ERR_USER_ON_CHANNEL);
1319 /* Generate new channel key as protocol dictates */
1321 silc_server_create_channel_key(server, channel, 0);
1323 /* Join the client to the channel by adding it to channel's user list.
1324 Add also the channel to client entry's channels list for fast cross-
1326 chl = silc_calloc(1, sizeof(*chl));
1328 chl->client = client;
1329 chl->channel = channel;
1330 silc_list_add(channel->user_list, chl);
1331 silc_list_add(client->channels, chl);
1333 /* Encode Client ID Payload of the original client who wants to join */
1334 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1336 /* Encode command reply packet */
1337 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1338 SILC_PUT32_MSB(channel->mode, mode);
1339 if (!channel->topic) {
1341 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1342 SILC_STATUS_OK, 0, 3,
1343 2, channel->channel_name,
1344 strlen(channel->channel_name),
1345 3, chidp->data, chidp->len,
1349 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1350 SILC_STATUS_OK, 0, 4,
1351 2, channel->channel_name,
1352 strlen(channel->channel_name),
1353 3, chidp->data, chidp->len,
1356 strlen(channel->topic));
1359 if (server->server_type == SILC_ROUTER &&
1360 cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1361 /* We are router and server has forwarded this command to us. Send
1362 all replys to the server. */
1365 /* Send command reply destined to the original client */
1366 tmpid = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1367 silc_server_packet_send_dest(cmd->server, sock,
1368 SILC_PACKET_COMMAND_REPLY, 0,
1369 tmpid, cmd->packet->src_id_type,
1370 reply->data, reply->len, FALSE);
1372 /* Distribute new channel key to local cell and local clients. */
1373 silc_server_send_channel_key(server, sock, channel, TRUE);
1375 /* Distribute JOIN notify into the cell for everbody on the channel */
1376 silc_server_send_notify_to_channel(server, channel, FALSE,
1377 SILC_NOTIFY_TYPE_JOIN, 1,
1378 clidp->data, clidp->len);
1380 /* Broadcast NEW_CHANNEL_USER packet to primary route */
1381 silc_server_send_new_channel_user(server, server->router->connection,
1382 TRUE, channel->id, SILC_ID_CHANNEL_LEN,
1383 client->id, SILC_ID_CLIENT_LEN);
1387 /* Client sent the command. Send all replies directly to the client. */
1389 /* Send command reply */
1390 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1391 reply->data, reply->len, FALSE);
1393 /* Send the channel key. Channel key is sent before any other packet
1395 silc_server_send_channel_key(server, sock, channel, server->standalone ?
1398 /* Send JOIN notify to locally connected clients on the channel */
1399 silc_server_send_notify_to_channel(server, channel, FALSE,
1400 SILC_NOTIFY_TYPE_JOIN, 1,
1401 clidp->data, clidp->len);
1403 /* Send NEW_CHANNEL_USER packet to our primary router */
1404 if (!server->standalone)
1405 silc_server_send_new_channel_user(server, server->router->connection,
1407 channel->id, SILC_ID_CHANNEL_LEN,
1408 client->id, SILC_ID_CLIENT_LEN);
1410 /* Send NAMES command reply to the joined channel so the user sees who
1411 is currently on the channel. */
1412 silc_server_command_send_names(server, sock, channel);
1415 silc_buffer_free(reply);
1416 silc_buffer_free(clidp);
1417 silc_buffer_free(chidp);
1421 silc_free(passphrase);
1424 /* Server side of command JOIN. Joins client into requested channel. If
1425 the channel does not exist it will be created. */
1427 SILC_SERVER_CMD_FUNC(join)
1429 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1430 SilcServer server = cmd->server;
1432 char *tmp, *channel_name = NULL, *cipher = NULL;
1433 SilcChannelEntry channel;
1434 unsigned int umode = 0;
1435 int created = FALSE;
1437 SILC_LOG_DEBUG(("Start"));
1439 /* Check number of parameters */
1440 argc = silc_argument_get_arg_num(cmd->args);
1442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1443 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1448 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1452 /* Get channel name */
1453 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1456 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1461 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1462 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1463 SILC_STATUS_ERR_BAD_CHANNEL);
1464 silc_free(channel_name);
1468 /* Get cipher name */
1469 cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1471 /* See if the channel exists */
1472 channel = silc_idlist_find_channel_by_name(server->local_list, channel_name);
1474 /* Channel not found */
1476 /* If we are standalone server we don't have a router, we just create
1477 the channel by ourselves. */
1478 if (server->standalone) {
1479 channel = silc_server_create_new_channel(server, server->id, cipher,
1481 umode |= SILC_CHANNEL_UMODE_CHANOP;
1482 umode |= SILC_CHANNEL_UMODE_CHANFO;
1486 /* The channel does not exist on our server. If we are normal server
1487 we will send JOIN command to our router which will handle the joining
1488 procedure (either creates the channel if it doesn't exist or joins
1489 the client to it). */
1490 if (server->server_type == SILC_SERVER) {
1491 /* Forward the original JOIN command to the router */
1492 silc_buffer_push(cmd->packet->buffer,
1493 cmd->packet->buffer->data -
1494 cmd->packet->buffer->head);
1495 silc_server_packet_forward(server, (SilcSocketConnection)
1496 server->router->connection,
1497 cmd->packet->buffer->data,
1498 cmd->packet->buffer->len, TRUE);
1502 /* We are router and the channel does not seem exist so we will check
1503 our global list as well for the channel. */
1504 channel = silc_idlist_find_channel_by_name(server->global_list,
1507 /* Channel really does not exist, create it */
1508 channel = silc_server_create_new_channel(server, server->id, cipher,
1510 umode |= SILC_CHANNEL_UMODE_CHANOP;
1511 umode |= SILC_CHANNEL_UMODE_CHANFO;
1517 /* Join to the channel */
1518 silc_server_command_join_channel(server, cmd, channel, created, umode);
1521 silc_server_command_free(cmd);
1524 /* Server side of command MOTD. Sends server's current "message of the
1525 day" to the client. */
1527 SILC_SERVER_CMD_FUNC(motd)
1529 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1530 SilcServer server = cmd->server;
1535 SILC_LOG_DEBUG(("Start"));
1537 argc = silc_argument_get_arg_num(cmd->args);
1539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1540 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1544 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1545 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1549 /* XXX show currently only our motd */
1551 if (server->config && server->config->motd &&
1552 server->config->motd->motd_file) {
1555 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
1560 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
1566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
1571 silc_server_command_free(cmd);
1574 SILC_SERVER_CMD_FUNC(umode)
1578 /* Checks that client has rights to add or remove channel modes. If any
1579 of the checks fails FALSE is returned. */
1581 int silc_server_check_cmode_rights(SilcChannelEntry channel,
1582 SilcChannelClientEntry client,
1585 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1586 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1588 /* Check whether has rights to change anything */
1589 if (!is_op && !is_fo)
1592 /* Check whether has rights to change everything */
1596 /* We know that client is channel operator, check that they are not
1597 changing anything that requires channel founder rights. Rest of the
1598 modes are available automatically for channel operator. */
1600 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1601 if (is_op && !is_fo)
1604 if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
1605 if (is_op && !is_fo)
1610 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1611 if (is_op && !is_fo)
1614 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1615 if (is_op && !is_fo)
1620 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1621 if (is_op && !is_fo)
1624 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1625 if (is_op && !is_fo)
1633 /* Server side command of CMODE. Changes channel mode */
1635 SILC_SERVER_CMD_FUNC(cmode)
1637 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1638 SilcServer server = cmd->server;
1639 SilcSocketConnection sock = cmd->sock;
1640 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1641 SilcChannelID *channel_id;
1642 SilcClientID *client_id;
1643 SilcChannelEntry channel;
1644 SilcChannelClientEntry chl;
1645 SilcBuffer packet, cidp;
1646 unsigned char *tmp, *tmp_id, *tmp_mask;
1647 unsigned int argc, mode_mask, tmp_len, tmp_len2;
1650 SILC_LOG_DEBUG(("Start"));
1652 argc = silc_argument_get_arg_num(cmd->args);
1654 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1655 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1659 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1660 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1664 /* Get Channel ID */
1665 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
1667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1668 SILC_STATUS_ERR_NO_CHANNEL_ID);
1671 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
1673 /* Get the channel mode mask */
1674 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1676 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1677 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1680 SILC_GET32_MSB(mode_mask, tmp_mask);
1682 /* Get channel entry */
1683 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1685 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1686 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1690 /* Check whether this client is on the channel */
1691 if (!silc_server_client_on_channel(client, channel)) {
1692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1693 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1697 /* Get entry to the channel user list */
1698 silc_list_start(channel->user_list);
1699 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1700 if (chl->client == client)
1703 /* Check that client has rights to change any requested channel modes */
1704 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
1705 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1706 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1711 * Check the modes. Modes that requires nothing special operation are
1715 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
1716 /* Channel uses private keys to protect traffic. Client(s) has set the
1717 key locally they want to use, server does not know that key. */
1718 /* Nothing interesting to do here now */
1720 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1721 /* The mode is removed and we need to generate and distribute
1722 new channel key. Clients are not using private channel keys
1723 anymore after this. */
1725 /* XXX Duplicated code, make own function for this!! LEAVE uses this
1728 /* Re-generate channel key */
1729 silc_server_create_channel_key(server, channel, 0);
1731 /* Encode channel key payload to be distributed on the channel */
1733 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1734 strlen(channel->channel_key->
1736 channel->channel_key->cipher->name,
1737 channel->key_len / 8, channel->key);
1739 /* If we are normal server then we will send it to our router. If we
1740 are router we will send it to all local servers that has clients on
1742 if (server->server_type == SILC_SERVER) {
1743 if (!server->standalone)
1744 silc_server_packet_send(server,
1745 cmd->server->router->connection,
1746 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1752 /* Send to locally connected clients on the channel */
1753 silc_server_packet_send_local_channel(server, channel,
1754 SILC_PACKET_CHANNEL_KEY, 0,
1755 packet->data, packet->len, FALSE);
1756 silc_buffer_free(packet);
1760 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
1761 /* User limit is set on channel */
1762 unsigned int user_limit;
1764 /* Get user limit */
1765 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1767 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
1768 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1769 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1773 SILC_GET32_MSB(user_limit, tmp);
1774 channel->mode_data.user_limit = user_limit;
1777 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
1778 /* User limit mode is unset. Remove user limit */
1779 channel->mode_data.user_limit = 0;
1782 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
1783 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1784 /* Passphrase has been set to channel */
1786 /* Get the passphrase */
1787 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1789 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1790 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1794 /* Save the passphrase */
1795 channel->mode_data.passphrase = strdup(tmp);
1798 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1799 /* Passphrase mode is unset. remove the passphrase */
1800 if (channel->mode_data.passphrase) {
1801 silc_free(channel->mode_data.passphrase);
1802 channel->mode_data.passphrase = NULL;
1807 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
1808 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
1809 /* Ban list is specified for channel */
1812 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1815 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1819 /* XXX check that channel founder is not banned */
1821 /* Save the ban list */
1822 channel->mode_data.ban_list = strdup(tmp);
1825 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1826 /* Ban mode is unset. Remove the entire ban list */
1827 if (channel->mode_data.ban_list) {
1828 silc_free(channel->mode_data.ban_list);
1829 channel->mode_data.ban_list = NULL;
1834 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
1835 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
1836 /* Invite list is specified for channel */
1838 /* Get invite list */
1839 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1842 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1846 /* Save the invite linst */
1847 channel->mode_data.invite_list = strdup(tmp);
1850 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1851 /* Invite list mode is unset. Remove the entire invite list */
1852 if (channel->mode_data.invite_list) {
1853 silc_free(channel->mode_data.invite_list);
1854 channel->mode_data.invite_list = NULL;
1859 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
1860 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1861 /* Cipher to use protect the traffic */
1862 unsigned int key_len = 128;
1866 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
1868 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1869 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1873 cp = strchr(tmp, ':');
1879 /* XXX Duplicated code, make own function for this!! */
1881 /* Delete old cipher and allocate the new one */
1882 silc_cipher_free(channel->channel_key);
1883 silc_cipher_alloc(tmp, &channel->channel_key);
1889 /* Re-generate channel key */
1890 silc_server_create_channel_key(server, channel, key_len);
1892 /* Encode channel key payload to be distributed on the channel */
1894 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1895 strlen(channel->channel_key->
1897 channel->channel_key->cipher->name,
1898 channel->key_len / 8, channel->key);
1900 /* If we are normal server then we will send it to our router. If we
1901 are router we will send it to all local servers that has clients on
1903 if (server->server_type == SILC_SERVER) {
1904 if (!server->standalone)
1905 silc_server_packet_send(server,
1906 cmd->server->router->connection,
1907 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1913 /* Send to locally connected clients on the channel */
1914 silc_server_packet_send_local_channel(server, channel,
1915 SILC_PACKET_CHANNEL_KEY, 0,
1916 packet->data, packet->len, FALSE);
1917 silc_buffer_free(packet);
1920 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1921 /* Cipher mode is unset. Remove the cipher and revert back to
1924 if (channel->mode_data.cipher) {
1925 silc_free(channel->mode_data.cipher);
1926 channel->mode_data.cipher = NULL;
1927 channel->mode_data.key_len = 0;
1930 /* Generate new cipher and key for the channel */
1932 /* XXX Duplicated code, make own function for this!! */
1934 /* Delete old cipher and allocate default one */
1935 silc_cipher_free(channel->channel_key);
1936 if (!channel->cipher)
1937 silc_cipher_alloc("twofish", &channel->channel_key);
1939 silc_cipher_alloc(channel->cipher, &channel->channel_key);
1941 /* Re-generate channel key */
1942 silc_server_create_channel_key(server, channel, 0);
1944 /* Encode channel key payload to be distributed on the channel */
1946 silc_channel_key_payload_encode(tmp_len2, tmp_id,
1947 strlen(channel->channel_key->
1949 channel->channel_key->cipher->name,
1950 channel->key_len / 8, channel->key);
1952 /* If we are normal server then we will send it to our router. If we
1953 are router we will send it to all local servers that has clients on
1955 if (server->server_type == SILC_SERVER) {
1956 if (!server->standalone)
1957 silc_server_packet_send(server,
1958 cmd->server->router->connection,
1959 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1965 /* Send to locally connected clients on the channel */
1966 silc_server_packet_send_local_channel(server, channel,
1967 SILC_PACKET_CHANNEL_KEY, 0,
1968 packet->data, packet->len, FALSE);
1969 silc_buffer_free(packet);
1973 /* Finally, set the mode */
1974 channel->mode = mode_mask;
1976 /* Send CMODE_CHANGE notify */
1977 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1978 silc_server_send_notify_to_channel(server, channel, TRUE,
1979 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
1980 cidp->data, cidp->len,
1984 /* Send command reply to sender */
1985 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
1986 SILC_STATUS_OK, 0, 1,
1988 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1989 packet->data, packet->len, FALSE);
1991 silc_buffer_free(packet);
1992 silc_free(channel_id);
1995 silc_server_command_free(cmd);
1998 /* Server side of CUMODE command. Changes client's mode on a channel. */
2000 SILC_SERVER_CMD_FUNC(cumode)
2002 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2003 SilcServer server = cmd->server;
2004 SilcSocketConnection sock = cmd->sock;
2005 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2006 SilcChannelID *channel_id;
2007 SilcClientID *client_id;
2008 SilcChannelEntry channel;
2009 SilcClientEntry target_client;
2010 SilcChannelClientEntry chl;
2011 SilcBuffer packet, idp;
2012 unsigned char *tmp, *tmp_id, *tmp_mask;
2013 unsigned int argc, target_mask, sender_mask, tmp_len;
2014 int i, notify = FALSE;
2016 SILC_LOG_DEBUG(("Start"));
2018 argc = silc_argument_get_arg_num(cmd->args);
2020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2021 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2025 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2026 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2030 /* Get Channel ID */
2031 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2033 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2034 SILC_STATUS_ERR_NO_CHANNEL_ID);
2037 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2039 /* Get channel entry */
2040 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
2042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2043 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2047 /* Check whether sender is on the channel */
2048 if (!silc_server_client_on_channel(client, channel)) {
2049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2050 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2054 /* Check that client has rights to change other's rights */
2055 silc_list_start(channel->user_list);
2056 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2057 if (chl->client == client) {
2058 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2059 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2060 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2061 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2065 sender_mask = chl->mode;
2070 /* Get the target client's channel mode mask */
2071 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2074 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2077 SILC_GET32_MSB(target_mask, tmp_mask);
2079 /* Get target Client ID */
2080 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2083 SILC_STATUS_ERR_NO_CHANNEL_ID);
2086 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2088 /* Get target client's entry */
2089 target_client = silc_idlist_find_client_by_id(server->local_list, client_id);
2090 if (!target_client) {
2091 /* XXX If target client is not one of mine send to primary route */
2094 /* Check whether target client is on the channel */
2095 if (!silc_server_client_on_channel(target_client, channel)) {
2096 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2097 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2101 /* Get entry to the channel user list */
2102 silc_list_start(channel->user_list);
2103 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2104 if (chl->client == target_client)
2111 /* If the target client is founder, no one else can change their mode
2113 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2114 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2115 SILC_STATUS_ERR_NOT_YOU);
2119 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2120 /* Cannot promote anyone to channel founder */
2121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2122 SILC_STATUS_ERR_NOT_YOU);
2125 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2126 if (target_client == client) {
2127 /* Remove channel founder rights from itself */
2128 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2131 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2132 SILC_STATUS_ERR_NOT_YOU);
2138 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2139 /* Promote to operator */
2140 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2141 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2145 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2146 /* Demote to normal user */
2147 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2152 /* Send notify to channel, notify only if mode was actually changed. */
2154 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2155 silc_server_send_notify_to_channel(server, channel, TRUE,
2156 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2157 idp->data, idp->len,
2158 tmp_mask, 4, tmp_id, tmp_len);
2159 silc_buffer_free(idp);
2162 /* Send command reply to sender */
2163 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2164 SILC_STATUS_OK, 0, 2,
2166 3, tmp_id, tmp_len);
2167 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2168 packet->data, packet->len, FALSE);
2170 silc_buffer_free(packet);
2171 silc_free(channel_id);
2172 silc_free(client_id);
2175 silc_server_command_free(cmd);
2178 /* Server side of KICK command. Kicks client out of channel. */
2180 SILC_SERVER_CMD_FUNC(kick)
2182 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2183 SilcServer server = cmd->server;
2184 SilcSocketConnection sock = cmd->sock;
2185 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2189 SILC_SERVER_CMD_FUNC(restart)
2193 SILC_SERVER_CMD_FUNC(close)
2197 SILC_SERVER_CMD_FUNC(die)
2201 SILC_SERVER_CMD_FUNC(silcoper)
2205 /* Server side command of LEAVE. Removes client from a channel. */
2207 SILC_SERVER_CMD_FUNC(leave)
2209 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2210 SilcServer server = cmd->server;
2211 SilcSocketConnection sock = cmd->sock;
2212 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2214 SilcChannelEntry channel;
2216 unsigned int i, argc, len;
2219 SILC_LOG_DEBUG(("Start"));
2221 argc = silc_argument_get_arg_num(cmd->args);
2223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2224 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2228 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2229 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2233 /* Get Channel ID */
2234 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2236 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2237 SILC_STATUS_ERR_NO_CHANNEL_ID);
2240 id = silc_id_payload_parse_id(tmp, len);
2242 /* Get channel entry */
2243 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2245 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2246 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2250 /* Check whether this client is on the channel */
2251 if (!silc_server_client_on_channel(id_entry, channel)) {
2252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2253 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2257 /* Notify routers that they should remove this client from their list
2258 of clients on the channel. */
2259 if (!server->standalone)
2260 silc_server_send_remove_channel_user(server,
2261 server->router->connection,
2262 server->server_type == SILC_ROUTER ?
2263 TRUE : FALSE, id_entry->id, id);
2265 /* Remove client from channel */
2266 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2271 /* If the channel does not exist anymore we won't send anything */
2275 /* Re-generate channel key */
2276 silc_server_create_channel_key(server, channel, 0);
2278 /* Encode channel key payload to be distributed on the channel */
2280 silc_channel_key_payload_encode(len, tmp,
2281 strlen(channel->channel_key->cipher->name),
2282 channel->channel_key->cipher->name,
2283 channel->key_len / 8, channel->key);
2285 /* If we are normal server then we will send it to our router. If we
2286 are router we will send it to all local servers that has clients on
2288 if (server->server_type == SILC_SERVER) {
2289 if (!server->standalone)
2290 silc_server_packet_send(server,
2291 cmd->server->router->connection,
2292 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2298 /* Send to locally connected clients on the channel */
2299 silc_server_packet_send_local_channel(server, channel,
2300 SILC_PACKET_CHANNEL_KEY, 0,
2301 packet->data, packet->len, FALSE);
2303 silc_buffer_free(packet);
2307 silc_server_command_free(cmd);
2310 /* Server side of command NAMES. Resolves clients and their names currently
2311 joined on the requested channel. The name list is sent back to the
2314 SILC_SERVER_CMD_FUNC(names)
2316 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2317 SilcServer server = cmd->server;
2318 SilcChannelEntry channel;
2319 SilcChannelClientEntry chl;
2322 unsigned int i, len, len2, tmp_len, argc;
2324 char *name_list = NULL, *n;
2325 SilcBuffer client_id_list;
2326 SilcBuffer client_mode_list;
2328 SILC_LOG_DEBUG(("Start"));
2330 argc = silc_argument_get_arg_num(cmd->args);
2332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2333 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2338 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2342 /* Get Channel ID */
2343 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2346 SILC_STATUS_ERR_NO_CHANNEL_ID);
2349 id = silc_id_payload_parse_id(tmp, tmp_len);
2351 /* Check whether the channel exists. If we are normal server and the
2352 channel does not exist we will send this same command to our router
2353 which will know if the channel exists. */
2354 channel = silc_idlist_find_channel_by_id(server->local_list, id);
2356 if (server->server_type == SILC_SERVER && !server->standalone) {
2357 /* XXX Send names command */
2359 cmd->pending = TRUE;
2360 silc_server_command_pending(server, SILC_COMMAND_NAMES, 0,
2361 silc_server_command_names, context);
2365 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2366 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2370 /* Assemble the name list now */
2373 silc_list_start(channel->user_list);
2375 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2376 n = chl->client->nickname;
2380 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2381 memcpy(name_list + (len - len2), n, len2);
2384 if (i == silc_list_count(channel->user_list) - 1)
2386 memcpy(name_list + len, ",", 1);
2394 /* Assemble the Client ID list now */
2395 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2396 silc_list_count(channel->user_list));
2397 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2398 silc_list_start(channel->user_list);
2399 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2402 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2403 silc_buffer_format(client_id_list,
2404 SILC_STR_UI_XNSTRING(idp->data, idp->len),
2406 silc_buffer_pull(client_id_list, idp->len);
2407 silc_buffer_free(idp);
2409 silc_buffer_push(client_id_list,
2410 client_id_list->data - client_id_list->head);
2412 /* Assemble mode list */
2413 client_mode_list = silc_buffer_alloc(4 *
2414 silc_list_count(channel->user_list));
2415 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2416 silc_list_start(channel->user_list);
2417 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2418 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2419 silc_buffer_pull(client_mode_list, 4);
2421 silc_buffer_push(client_mode_list,
2422 client_mode_list->data - client_mode_list->head);
2425 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2426 SILC_STATUS_OK, 0, 4,
2430 4, client_id_list->data,
2431 client_id_list->len,
2432 5, client_mode_list->data,
2433 client_mode_list->len);
2434 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2435 packet->data, packet->len, FALSE);
2437 silc_buffer_free(packet);
2438 silc_free(name_list);
2439 silc_buffer_free(client_id_list);
2440 silc_buffer_free(client_mode_list);
2444 silc_server_command_free(cmd);