5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
37 unsigned int arg_type,
39 unsigned int arg_len);
40 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
45 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
49 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
54 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(connect, CONNECT,
56 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(restart, RESTART,
66 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
67 SILC_SERVER_CMD(close, CLOSE,
68 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
69 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
71 SILC_SERVER_CMD(silcoper, SILCOPER,
72 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
73 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
74 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
79 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
81 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
83 SILC_LOG_DEBUG(("Start")); \
86 silc_server_command_send_status_reply(cmd, command, \
87 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
88 silc_server_command_free(cmd); \
92 silc_server_command_send_status_reply(cmd, command, \
93 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
94 silc_server_command_free(cmd); \
99 /* Returns TRUE if the connection is registered. Unregistered connections
100 usually cannot send commands hence the check. */
102 static int silc_server_is_registered(SilcServer server,
103 SilcSocketConnection sock,
104 SilcServerCommandContext cmd,
107 SilcIDListData idata = (SilcIDListData)sock->user_data;
108 if (idata->registered)
111 silc_server_command_send_status_reply(cmd, command,
112 SILC_STATUS_ERR_NOT_REGISTERED);
113 silc_server_command_free(cmd);
117 /* Internal context to hold data when executed command with timeout. */
120 SilcSocketConnection sock;
121 SilcPacketContext *packet;
122 } *SilcServerCommandTimeout;
124 /* Timeout callback to process commands with timeout for client. Client's
125 commands are always executed with timeout. */
127 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
129 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
130 SilcServerCommandContext ctx;
131 SilcServerCommand *cmd;
132 SilcClientEntry client = (SilcClientEntry)timeout->sock->user_data;
134 /* Update access time */
135 client->last_command = time(NULL);
137 /* Allocate command context. This must be free'd by the
138 command routine receiving it. */
139 ctx = silc_server_command_alloc();
140 ctx->server = timeout->server;
141 ctx->sock = timeout->sock;
142 ctx->packet = timeout->packet;
144 /* Parse the command payload in the packet */
145 ctx->payload = silc_command_payload_parse(ctx->packet->buffer);
147 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
148 silc_buffer_free(ctx->packet->buffer);
149 silc_socket_free(ctx->sock);
150 silc_packet_context_free(ctx->packet);
155 ctx->args = silc_command_get_args(ctx->payload);
157 /* Execute command. If this fails the packet is dropped. */
158 for (cmd = silc_command_list; cmd->cb; cmd++)
159 if (cmd->cmd == silc_command_get(ctx->payload)) {
161 if (!(cmd->flags & SILC_CF_REG)) {
166 if (silc_server_is_registered(ctx->server, ctx->sock, ctx, cmd->cmd)) {
173 SILC_LOG_ERROR(("Unknown command, packet dropped"));
174 silc_server_command_free(ctx);
182 /* Processes received command packet. */
184 void silc_server_command_process(SilcServer server,
185 SilcSocketConnection sock,
186 SilcPacketContext *packet)
188 SilcServerCommandContext ctx;
189 SilcServerCommand *cmd;
191 /* Execute client's commands always with timeout. Normally they are
192 executed with zero (0) timeout but if client is sending command more
193 frequently than once in 2 seconds, then the timeout may be 0 to 2
195 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
196 SilcClientEntry client = (SilcClientEntry)sock->user_data;
197 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
199 timeout->server = server;
200 timeout->sock = silc_socket_dup(sock);
201 timeout->packet = silc_packet_context_dup(packet);
203 if (client->last_command && (time(NULL) - client->last_command) < 2)
204 silc_task_register(server->timeout_queue, sock->sock,
205 silc_server_command_process_timeout,
207 2 - (time(NULL) - client->last_command), 0,
209 SILC_TASK_PRI_NORMAL);
211 silc_task_register(server->timeout_queue, sock->sock,
212 silc_server_command_process_timeout,
216 SILC_TASK_PRI_NORMAL);
220 /* Allocate command context. This must be free'd by the
221 command routine receiving it. */
222 ctx = silc_server_command_alloc();
223 ctx->server = server;
224 ctx->sock = silc_socket_dup(sock);
225 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
227 /* Parse the command payload in the packet */
228 ctx->payload = silc_command_payload_parse(packet->buffer);
230 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
231 silc_buffer_free(packet->buffer);
232 silc_packet_context_free(packet);
233 silc_socket_free(ctx->sock);
237 ctx->args = silc_command_get_args(ctx->payload);
239 /* Execute command. If this fails the packet is dropped. */
240 for (cmd = silc_command_list; cmd->cb; cmd++)
241 if (cmd->cmd == silc_command_get(ctx->payload)) {
243 if (!(cmd->flags & SILC_CF_REG)) {
248 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
255 SILC_LOG_ERROR(("Unknown command, packet dropped"));
256 silc_server_command_free(ctx);
261 /* Allocate Command Context */
263 SilcServerCommandContext silc_server_command_alloc()
265 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
270 /* Free's the command context allocated before executing the command */
272 void silc_server_command_free(SilcServerCommandContext ctx)
275 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
277 if (ctx->users < 1) {
279 silc_command_free_payload(ctx->payload);
281 silc_packet_context_free(ctx->packet);
283 silc_socket_free(ctx->sock); /* Decrease reference counter */
288 /* Duplicate Command Context by adding reference counter. The context won't
289 be free'd untill it hits zero. */
291 SilcServerCommandContext
292 silc_server_command_dup(SilcServerCommandContext ctx)
295 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
300 /* Add new pending command to be executed when reply to a command has been
301 received. The `reply_cmd' is the command that will call the `callback'
302 with `context' when reply has been received. If `ident' is non-zero
303 the `callback' will be executed when received reply with command
304 identifier `ident'. */
306 void silc_server_command_pending(SilcServer server,
307 SilcCommand reply_cmd,
308 unsigned short ident,
309 SilcServerPendingDestructor destructor,
310 SilcCommandCb callback,
313 SilcServerCommandPending *reply;
315 reply = silc_calloc(1, sizeof(*reply));
316 reply->reply_cmd = reply_cmd;
317 reply->ident = ident;
318 reply->context = context;
319 reply->callback = callback;
320 reply->destructor = destructor;
321 silc_dlist_add(server->pending_commands, reply);
324 /* Deletes pending command by reply command type. */
326 void silc_server_command_pending_del(SilcServer server,
327 SilcCommand reply_cmd,
328 unsigned short ident)
330 SilcServerCommandPending *r;
332 silc_dlist_start(server->pending_commands);
333 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
334 if (r->reply_cmd == reply_cmd && r->ident == ident) {
335 silc_dlist_del(server->pending_commands, r);
341 /* Checks for pending commands and marks callbacks to be called from
342 the command reply function. Returns TRUE if there were pending command. */
344 int silc_server_command_pending_check(SilcServer server,
345 SilcServerCommandReplyContext ctx,
347 unsigned short ident)
349 SilcServerCommandPending *r;
351 silc_dlist_start(server->pending_commands);
352 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
353 if (r->reply_cmd == command && r->ident == ident) {
354 ctx->context = r->context;
355 ctx->callback = r->callback;
356 ctx->destructor = r->destructor;
365 /* Destructor function for pending callbacks. This is called when using
366 pending commands to free the context given for the pending command. */
368 static void silc_server_command_destructor(void *context)
370 silc_server_command_free((SilcServerCommandContext)context);
373 /* Sends simple status message as command reply packet */
376 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
378 SilcCommandStatus status)
382 SILC_LOG_DEBUG(("Sending command status %d", status));
384 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
385 silc_server_packet_send(cmd->server, cmd->sock,
386 SILC_PACKET_COMMAND_REPLY, 0,
387 buffer->data, buffer->len, FALSE);
388 silc_buffer_free(buffer);
391 /* Sends command status reply with one extra argument. The argument
392 type must be sent as argument. */
395 silc_server_command_send_status_data(SilcServerCommandContext cmd,
397 SilcCommandStatus status,
398 unsigned int arg_type,
400 unsigned int arg_len)
404 SILC_LOG_DEBUG(("Sending command status %d", status));
406 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
407 arg_type, arg, arg_len);
408 silc_server_packet_send(cmd->server, cmd->sock,
409 SILC_PACKET_COMMAND_REPLY, 0,
410 buffer->data, buffer->len, FALSE);
411 silc_buffer_free(buffer);
414 /******************************************************************************
418 ******************************************************************************/
421 silc_server_command_whois_parse(SilcServerCommandContext cmd,
422 SilcClientID ***client_id,
423 unsigned int *client_id_count,
431 unsigned int argc = silc_argument_get_arg_num(cmd->args);
434 /* If client ID is in the command it must be used instead of nickname */
435 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
437 /* No ID, get the nickname@server string and parse it. */
438 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
440 if (strchr(tmp, '@')) {
441 len = strcspn(tmp, "@");
442 *nickname = silc_calloc(len + 1, sizeof(char));
443 memcpy(*nickname, tmp, len);
444 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
445 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
447 *nickname = strdup(tmp);
450 silc_server_command_send_status_reply(cmd, command,
451 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
455 /* Command includes ID, we must use that. Also check whether the command
456 has more than one ID set - take them all. */
458 *client_id = silc_calloc(1, sizeof(**client_id));
459 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
460 if ((*client_id)[0] == NULL) {
461 silc_free(*client_id);
464 *client_id_count = 1;
466 /* Take all ID's from the command packet */
468 for (k = 1, i = 1; i < argc; i++) {
469 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
471 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
472 (*client_id_count + 1));
473 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
474 if ((*client_id)[k] == NULL) {
475 /* Cleanup all and fail */
476 for (i = 0; i < *client_id_count; i++)
477 silc_free((*client_id)[i]);
478 silc_free(*client_id);
481 (*client_id_count)++;
487 /* Command includes ID, use that */
490 /* Get the max count of reply messages allowed */
491 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
501 silc_server_command_whois_check(SilcServerCommandContext cmd,
502 SilcClientEntry *clients,
503 unsigned int clients_count)
505 SilcServer server = cmd->server;
507 SilcClientEntry entry;
509 for (i = 0; i < clients_count; i++) {
512 if (!entry->nickname || !entry->username) {
514 unsigned short old_ident;
519 old_ident = silc_command_get_ident(cmd->payload);
520 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
521 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
523 /* Send WHOIS command */
524 silc_server_packet_send(server, entry->router->connection,
525 SILC_PACKET_COMMAND, cmd->packet->flags,
526 tmpbuf->data, tmpbuf->len, TRUE);
528 /* Reprocess this packet after received reply */
529 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
530 silc_command_get_ident(cmd->payload),
531 silc_server_command_destructor,
532 silc_server_command_whois,
533 silc_server_command_dup(cmd));
536 silc_command_set_ident(cmd->payload, old_ident);
538 silc_buffer_free(tmpbuf);
547 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
548 SilcClientEntry *clients,
549 unsigned int clients_count)
551 SilcServer server = cmd->server;
553 int i, count = 0, len;
554 SilcBuffer packet, idp;
555 SilcClientEntry entry;
556 SilcCommandStatus status;
557 unsigned short ident = silc_command_get_ident(cmd->payload);
559 status = SILC_STATUS_OK;
560 if (clients_count > 1)
561 status = SILC_STATUS_LIST_START;
563 for (i = 0; i < clients_count; i++) {
566 if (entry->data.registered == FALSE) {
567 if (clients_count == 1)
568 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
569 SILC_STATUS_ERR_NO_SUCH_NICK,
571 strlen(entry->nickname));
575 if (count && i - 1 == count)
578 if (clients_count > 2)
579 status = SILC_STATUS_LIST_ITEM;
581 if (clients_count > 1 && i == clients_count - 1)
582 status = SILC_STATUS_LIST_END;
584 /* Sanity check, however these should never fail. However, as
585 this sanity check has been added here they have failed. */
586 if (!entry->nickname || !entry->username)
589 /* Send WHOIS reply */
590 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
591 tmp = silc_argument_get_first_arg(cmd->args, NULL);
594 char nh[256], uh[256];
595 unsigned char idle[4];
596 SilcSocketConnection hsock;
598 memset(uh, 0, sizeof(uh));
599 memset(nh, 0, sizeof(nh));
601 strncat(nh, entry->nickname, strlen(entry->nickname));
602 if (!strchr(entry->nickname, '@')) {
604 len = entry->router ? strlen(entry->router->server_name) :
605 strlen(server->server_name);
606 strncat(nh, entry->router ? entry->router->server_name :
607 server->server_name, len);
610 strncat(uh, entry->username, strlen(entry->username));
611 if (!strchr(entry->username, '@')) {
613 hsock = (SilcSocketConnection)entry->connection;
614 len = strlen(hsock->hostname);
615 strncat(uh, hsock->hostname, len);
618 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
621 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
623 2, idp->data, idp->len,
627 strlen(entry->userinfo),
631 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
632 0, packet->data, packet->len, FALSE);
634 silc_buffer_free(packet);
635 silc_buffer_free(idp);
640 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
642 SilcServer server = cmd->server;
643 char *nick = NULL, *server_name = NULL;
644 int count = 0, clients_count = 0;
645 SilcClientEntry *clients = NULL, entry;
646 SilcClientID **client_id = NULL;
647 unsigned int client_id_count = 0;
650 /* Protocol dictates that we must always send the received WHOIS request
651 to our router if we are normal server, so let's do it now unless we
652 are standalone. We will not send any replies to the client until we
653 have received reply from the router. */
654 if (server->server_type == SILC_SERVER &&
655 !cmd->pending && !server->standalone) {
657 unsigned short old_ident;
659 old_ident = silc_command_get_ident(cmd->payload);
660 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
661 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
663 /* Send WHOIS command to our router */
664 silc_server_packet_send(server, (SilcSocketConnection)
665 server->router->connection,
666 SILC_PACKET_COMMAND, cmd->packet->flags,
667 tmpbuf->data, tmpbuf->len, TRUE);
669 /* Reprocess this packet after received reply from router */
670 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
671 silc_command_get_ident(cmd->payload),
672 silc_server_command_destructor,
673 silc_server_command_whois,
674 silc_server_command_dup(cmd));
677 silc_command_set_ident(cmd->payload, old_ident);
679 silc_buffer_free(tmpbuf);
684 /* We are ready to process the command request. Let's search for the
685 requested client and send reply to the requesting client. */
687 /* Parse the whois request */
688 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
689 &nick, &server_name, &count,
693 /* Get all clients matching that ID or nickname from local list */
694 if (client_id_count) {
695 /* Check all Client ID's received in the command packet */
696 for (i = 0; i < client_id_count; i++) {
697 entry = silc_idlist_find_client_by_id(server->local_list,
700 clients = silc_realloc(clients, sizeof(*clients) *
701 (clients_count + 1));
702 clients[clients_count++] = entry;
706 clients = silc_idlist_get_clients_by_nickname(server->local_list,
710 clients = silc_idlist_get_clients_by_hash(server->local_list,
711 nick, server->md5hash,
715 /* Check global list as well */
717 if (client_id_count) {
718 /* Check all Client ID's received in the command packet */
719 for (i = 0; i < client_id_count; i++) {
720 entry = silc_idlist_find_client_by_id(server->global_list,
723 clients = silc_realloc(clients, sizeof(*clients) *
724 (clients_count + 1));
725 clients[clients_count++] = entry;
729 clients = silc_idlist_get_clients_by_nickname(server->global_list,
733 clients = silc_idlist_get_clients_by_hash(server->global_list,
734 nick, server->md5hash,
740 /* Such client(s) really does not exist in the SILC network. */
741 if (!client_id_count) {
742 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
743 SILC_STATUS_ERR_NO_SUCH_NICK,
744 3, nick, strlen(nick));
746 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
747 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
748 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
749 2, idp->data, idp->len);
750 silc_buffer_free(idp);
755 /* Router always finds the client entry if it exists in the SILC network.
756 However, it might be incomplete entry and does not include all the
757 mandatory fields that WHOIS command reply requires. Check for these and
758 make query from the server who owns the client if some fields are
760 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
765 /* Send the command reply to the client */
766 silc_server_command_whois_send_reply(cmd, clients, clients_count);
769 if (client_id_count) {
770 for (i = 0; i < client_id_count; i++)
771 silc_free(client_id[i]);
772 silc_free(client_id);
779 silc_free(server_name);
785 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
787 SilcServer server = cmd->server;
788 char *nick = NULL, *server_name = NULL;
789 int count = 0, clients_count = 0;
790 SilcClientEntry *clients = NULL, entry;
791 SilcClientID **client_id = NULL;
792 unsigned int client_id_count = 0;
795 /* Parse the whois request */
796 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
797 &nick, &server_name, &count,
801 /* Process the command request. Let's search for the requested client and
802 send reply to the requesting server. */
804 if (client_id_count) {
805 /* Check all Client ID's received in the command packet */
806 for (i = 0; i < client_id_count; i++) {
807 entry = silc_idlist_find_client_by_id(server->local_list,
810 clients = silc_realloc(clients, sizeof(*clients) *
811 (clients_count + 1));
812 clients[clients_count++] = entry;
816 clients = silc_idlist_get_clients_by_nickname(server->local_list,
820 clients = silc_idlist_get_clients_by_hash(server->local_list,
821 nick, server->md5hash,
825 /* If we are router we will check our global list as well. */
826 if (!clients && server->server_type == SILC_ROUTER) {
827 if (client_id_count) {
828 /* Check all Client ID's received in the command packet */
829 for (i = 0; i < client_id_count; i++) {
830 entry = silc_idlist_find_client_by_id(server->global_list,
833 clients = silc_realloc(clients, sizeof(*clients) *
834 (clients_count + 1));
835 clients[clients_count++] = entry;
839 clients = silc_idlist_get_clients_by_nickname(server->global_list,
843 clients = silc_idlist_get_clients_by_hash(server->global_list,
844 nick, server->md5hash,
850 /* Such a client really does not exist in the SILC network. */
851 if (!client_id_count) {
852 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
853 SILC_STATUS_ERR_NO_SUCH_NICK,
854 3, nick, strlen(nick));
856 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
857 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
858 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
859 2, idp->data, idp->len);
860 silc_buffer_free(idp);
865 /* Router always finds the client entry if it exists in the SILC network.
866 However, it might be incomplete entry and does not include all the
867 mandatory fields that WHOIS command reply requires. Check for these and
868 make query from the server who owns the client if some fields are
870 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
875 /* Send the command reply to the client */
876 silc_server_command_whois_send_reply(cmd, clients, clients_count);
879 if (client_id_count) {
880 for (i = 0; i < client_id_count; i++)
881 silc_free(client_id[i]);
882 silc_free(client_id);
889 silc_free(server_name);
894 /* Server side of command WHOIS. Processes user's query and sends found
895 results as command replies back to the client. */
897 SILC_SERVER_CMD_FUNC(whois)
899 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
902 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
904 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
905 ret = silc_server_command_whois_from_client(cmd);
906 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
907 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
908 ret = silc_server_command_whois_from_server(cmd);
911 silc_server_command_free(cmd);
914 /******************************************************************************
918 ******************************************************************************/
921 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
929 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
931 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
932 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
936 /* Get the nickname@server string and parse it. */
937 if (strchr(tmp, '@')) {
938 len = strcspn(tmp, "@");
939 *nickname = silc_calloc(len + 1, sizeof(char));
940 memcpy(*nickname, tmp, len);
941 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
942 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
944 *nickname = strdup(tmp);
946 /* Get the max count of reply messages allowed */
947 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
957 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
958 SilcClientEntry *clients,
959 unsigned int clients_count)
961 SilcServer server = cmd->server;
963 int i, count = 0, len;
964 SilcBuffer packet, idp;
965 SilcClientEntry entry = NULL;
966 SilcCommandStatus status;
967 unsigned short ident = silc_command_get_ident(cmd->payload);
970 status = SILC_STATUS_OK;
971 if (clients_count > 1)
972 status = SILC_STATUS_LIST_START;
974 for (i = 0; i < clients_count; i++) {
977 /* We will take only clients that are not valid anymore. They are the
978 ones that are not registered anymore but still have a ID. They
979 have disconnected us, and thus valid for WHOWAS. */
980 if (entry->data.registered == TRUE)
982 if (entry->id == NULL)
985 if (count && i - 1 == count)
990 if (clients_count > 2)
991 status = SILC_STATUS_LIST_ITEM;
993 if (clients_count > 1 && i == clients_count - 1)
994 status = SILC_STATUS_LIST_END;
996 /* Sanity check, however these should never fail. However, as
997 this sanity check has been added here they have failed. */
998 if (!entry->nickname || !entry->username)
1001 /* Send WHOWAS reply */
1002 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1003 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1006 char nh[256], uh[256];
1008 memset(uh, 0, sizeof(uh));
1009 memset(nh, 0, sizeof(nh));
1011 strncat(nh, entry->nickname, strlen(entry->nickname));
1012 if (!strchr(entry->nickname, '@')) {
1013 strncat(nh, "@", 1);
1014 len = entry->router ? strlen(entry->router->server_name) :
1015 strlen(server->server_name);
1016 strncat(nh, entry->router ? entry->router->server_name :
1017 server->server_name, len);
1020 strncat(uh, entry->username, strlen(entry->username));
1021 if (!strchr(entry->username, '@')) {
1022 strncat(uh, "@", 1);
1023 strcat(uh, "*private*");
1027 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1029 2, idp->data, idp->len,
1033 strlen(entry->userinfo));
1036 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1037 0, packet->data, packet->len, FALSE);
1039 silc_buffer_free(packet);
1040 silc_buffer_free(idp);
1043 if (found == FALSE && entry)
1044 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1045 SILC_STATUS_ERR_NO_SUCH_NICK,
1047 strlen(entry->nickname));
1051 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1053 SilcServer server = cmd->server;
1054 char *nick = NULL, *server_name = NULL;
1055 int count = 0, clients_count = 0;
1056 SilcClientEntry *clients = NULL;
1059 /* Protocol dictates that we must always send the received WHOWAS request
1060 to our router if we are normal server, so let's do it now unless we
1061 are standalone. We will not send any replies to the client until we
1062 have received reply from the router. */
1063 if (server->server_type == SILC_SERVER &&
1064 !cmd->pending && !server->standalone) {
1066 unsigned short old_ident;
1068 old_ident = silc_command_get_ident(cmd->payload);
1069 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1070 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1072 /* Send WHOWAS command to our router */
1073 silc_server_packet_send(server, (SilcSocketConnection)
1074 server->router->connection,
1075 SILC_PACKET_COMMAND, cmd->packet->flags,
1076 tmpbuf->data, tmpbuf->len, TRUE);
1078 /* Reprocess this packet after received reply from router */
1079 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1080 silc_command_get_ident(cmd->payload),
1081 silc_server_command_destructor,
1082 silc_server_command_whois,
1083 silc_server_command_dup(cmd));
1084 cmd->pending = TRUE;
1086 silc_command_set_ident(cmd->payload, old_ident);
1088 silc_buffer_free(tmpbuf);
1093 /* We are ready to process the command request. Let's search for the
1094 requested client and send reply to the requesting client. */
1096 /* Parse the whowas request */
1097 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1100 /* Get all clients matching that nickname from local list */
1101 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1105 clients = silc_idlist_get_clients_by_hash(server->local_list,
1106 nick, server->md5hash,
1109 /* Check global list as well */
1111 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1115 clients = silc_idlist_get_clients_by_hash(server->global_list,
1116 nick, server->md5hash,
1121 /* Such client(s) really does not exist in the SILC network. */
1122 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1123 SILC_STATUS_ERR_NO_SUCH_NICK,
1124 3, nick, strlen(nick));
1128 /* Send the command reply to the client */
1129 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1137 silc_free(server_name);
1143 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1145 SilcServer server = cmd->server;
1146 char *nick = NULL, *server_name = NULL;
1147 int count = 0, clients_count = 0;
1148 SilcClientEntry *clients = NULL;
1151 /* Parse the whowas request */
1152 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1155 /* Process the command request. Let's search for the requested client and
1156 send reply to the requesting server. */
1158 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1162 clients = silc_idlist_get_clients_by_hash(server->local_list,
1163 nick, server->md5hash,
1166 /* If we are router we will check our global list as well. */
1167 if (!clients && server->server_type == SILC_ROUTER) {
1168 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1172 clients = silc_idlist_get_clients_by_hash(server->global_list,
1173 nick, server->md5hash,
1178 /* Such a client really does not exist in the SILC network. */
1179 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1180 SILC_STATUS_ERR_NO_SUCH_NICK,
1181 3, nick, strlen(nick));
1185 /* Send the command reply to the client */
1186 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1194 silc_free(server_name);
1199 /* Server side of command WHOWAS. */
1201 SILC_SERVER_CMD_FUNC(whowas)
1203 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1206 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1208 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1209 ret = silc_server_command_whowas_from_client(cmd);
1210 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1211 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1212 ret = silc_server_command_whowas_from_server(cmd);
1215 silc_server_command_free(cmd);
1218 /******************************************************************************
1222 ******************************************************************************/
1224 /* Checks that all mandatory fields are present. If not then send WHOIS
1225 request to the server who owns the client. We use WHOIS because we want
1226 to get as much information as possible at once. */
1229 silc_server_command_identify_check(SilcServerCommandContext cmd,
1230 SilcClientEntry *clients,
1231 unsigned int clients_count)
1233 SilcServer server = cmd->server;
1235 SilcClientEntry entry;
1237 for (i = 0; i < clients_count; i++) {
1240 if (!entry->nickname) {
1242 unsigned short old_ident;
1247 old_ident = silc_command_get_ident(cmd->payload);
1248 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1249 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1250 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1252 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1253 now anyway so make it a good one. */
1254 silc_server_packet_send(server, entry->router->connection,
1255 SILC_PACKET_COMMAND, cmd->packet->flags,
1256 tmpbuf->data, tmpbuf->len, TRUE);
1258 /* Reprocess this packet after received reply */
1259 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1260 silc_command_get_ident(cmd->payload),
1261 silc_server_command_destructor,
1262 silc_server_command_identify,
1263 silc_server_command_dup(cmd));
1265 cmd->pending = TRUE;
1267 /* Put old data back to the Command Payload we just changed */
1268 silc_command_set_ident(cmd->payload, old_ident);
1269 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1271 silc_buffer_free(tmpbuf);
1280 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1281 SilcClientEntry *clients,
1282 unsigned int clients_count)
1284 SilcServer server = cmd->server;
1286 int i, count = 0, len;
1287 SilcBuffer packet, idp;
1288 SilcClientEntry entry;
1289 SilcCommandStatus status;
1290 unsigned short ident = silc_command_get_ident(cmd->payload);
1292 status = SILC_STATUS_OK;
1293 if (clients_count > 1)
1294 status = SILC_STATUS_LIST_START;
1296 for (i = 0; i < clients_count; i++) {
1299 if (entry->data.registered == FALSE) {
1300 if (clients_count == 1)
1301 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1302 SILC_STATUS_ERR_NO_SUCH_NICK,
1304 strlen(entry->nickname));
1308 if (count && i - 1 == count)
1311 if (clients_count > 2)
1312 status = SILC_STATUS_LIST_ITEM;
1314 if (clients_count > 1 && i == clients_count - 1)
1315 status = SILC_STATUS_LIST_END;
1317 /* Send IDENTIFY reply */
1318 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1319 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1323 char nh[256], uh[256];
1324 SilcSocketConnection hsock;
1326 memset(uh, 0, sizeof(uh));
1327 memset(nh, 0, sizeof(nh));
1329 strncat(nh, entry->nickname, strlen(entry->nickname));
1330 if (!strchr(entry->nickname, '@')) {
1331 strncat(nh, "@", 1);
1332 len = entry->router ? strlen(entry->router->server_name) :
1333 strlen(server->server_name);
1334 strncat(nh, entry->router ? entry->router->server_name :
1335 server->server_name, len);
1338 if (!entry->username) {
1339 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1341 2, idp->data, idp->len,
1344 strncat(uh, entry->username, strlen(entry->username));
1345 if (!strchr(entry->username, '@')) {
1346 strncat(uh, "@", 1);
1347 hsock = (SilcSocketConnection)entry->connection;
1348 len = strlen(hsock->hostname);
1349 strncat(uh, hsock->hostname, len);
1352 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1354 2, idp->data, idp->len,
1359 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1360 0, packet->data, packet->len, FALSE);
1362 silc_buffer_free(packet);
1363 silc_buffer_free(idp);
1369 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1371 SilcServer server = cmd->server;
1372 char *nick = NULL, *server_name = NULL;
1373 int count = 0, clients_count = 0;
1374 SilcClientEntry *clients = NULL, entry;
1375 SilcClientID **client_id = NULL;
1376 unsigned int client_id_count = 0;
1379 /* Protocol dictates that we must always send the received IDENTIFY request
1380 to our router if we are normal server, so let's do it now unless we
1381 are standalone. We will not send any replies to the client until we
1382 have received reply from the router. */
1383 if (server->server_type == SILC_SERVER &&
1384 !cmd->pending && !server->standalone) {
1386 unsigned short old_ident;
1388 old_ident = silc_command_get_ident(cmd->payload);
1389 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1390 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1392 /* Send IDENTIFY command to our router */
1393 silc_server_packet_send(server, (SilcSocketConnection)
1394 server->router->connection,
1395 SILC_PACKET_COMMAND, cmd->packet->flags,
1396 tmpbuf->data, tmpbuf->len, TRUE);
1398 /* Reprocess this packet after received reply from router */
1399 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1400 silc_command_get_ident(cmd->payload),
1401 silc_server_command_destructor,
1402 silc_server_command_identify,
1403 silc_server_command_dup(cmd));
1404 cmd->pending = TRUE;
1406 silc_command_set_ident(cmd->payload, old_ident);
1408 silc_buffer_free(tmpbuf);
1413 /* We are ready to process the command request. Let's search for the
1414 requested client and send reply to the requesting client. */
1416 /* Parse the IDENTIFY request */
1417 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1418 &nick, &server_name, &count,
1419 SILC_COMMAND_IDENTIFY))
1422 /* Get all clients matching that ID or nickname from local list */
1423 if (client_id_count) {
1424 /* Check all Client ID's received in the command packet */
1425 for (i = 0; i < client_id_count; i++) {
1426 entry = silc_idlist_find_client_by_id(server->local_list,
1427 client_id[i], NULL);
1429 clients = silc_realloc(clients, sizeof(*clients) *
1430 (clients_count + 1));
1431 clients[clients_count++] = entry;
1435 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1439 clients = silc_idlist_get_clients_by_hash(server->local_list,
1440 nick, server->md5hash,
1444 /* Check global list as well */
1446 if (client_id_count) {
1447 /* Check all Client ID's received in the command packet */
1448 for (i = 0; i < client_id_count; i++) {
1449 entry = silc_idlist_find_client_by_id(server->global_list,
1450 client_id[i], NULL);
1452 clients = silc_realloc(clients, sizeof(*clients) *
1453 (clients_count + 1));
1454 clients[clients_count++] = entry;
1458 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1462 clients = silc_idlist_get_clients_by_hash(server->global_list,
1463 nick, server->md5hash,
1469 /* Such a client really does not exist in the SILC network. */
1470 if (!client_id_count) {
1471 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1472 SILC_STATUS_ERR_NO_SUCH_NICK,
1473 3, nick, strlen(nick));
1475 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1476 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1477 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1478 2, idp->data, idp->len);
1479 silc_buffer_free(idp);
1484 /* Check that all mandatory fields are present and request those data
1485 from the server who owns the client if necessary. */
1486 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1491 /* Send the command reply to the client */
1492 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1495 if (client_id_count) {
1496 for (i = 0; i < client_id_count; i++)
1497 silc_free(client_id[i]);
1498 silc_free(client_id);
1505 silc_free(server_name);
1511 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1513 SilcServer server = cmd->server;
1514 char *nick = NULL, *server_name = NULL;
1515 int count = 0, clients_count = 0;
1516 SilcClientEntry *clients = NULL, entry;
1517 SilcClientID **client_id = NULL;
1518 unsigned int client_id_count = 0;
1521 /* Parse the IDENTIFY request */
1522 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1523 &nick, &server_name, &count,
1524 SILC_COMMAND_IDENTIFY))
1527 /* Process the command request. Let's search for the requested client and
1528 send reply to the requesting server. */
1530 if (client_id_count) {
1531 /* Check all Client ID's received in the command packet */
1532 for (i = 0; i < client_id_count; i++) {
1533 entry = silc_idlist_find_client_by_id(server->local_list,
1534 client_id[i], NULL);
1536 clients = silc_realloc(clients, sizeof(*clients) *
1537 (clients_count + 1));
1538 clients[clients_count++] = entry;
1542 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1546 clients = silc_idlist_get_clients_by_hash(server->local_list,
1547 nick, server->md5hash,
1551 /* If we are router we will check our global list as well. */
1552 if (!clients && server->server_type == SILC_ROUTER) {
1553 if (client_id_count) {
1554 /* Check all Client ID's received in the command packet */
1555 for (i = 0; i < client_id_count; i++) {
1556 entry = silc_idlist_find_client_by_id(server->global_list,
1557 client_id[i], NULL);
1559 clients = silc_realloc(clients, sizeof(*clients) *
1560 (clients_count + 1));
1561 clients[clients_count++] = entry;
1565 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1569 clients = silc_idlist_get_clients_by_hash(server->global_list,
1570 nick, server->md5hash,
1576 /* Such a client really does not exist in the SILC network. */
1577 if (!client_id_count) {
1578 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1579 SILC_STATUS_ERR_NO_SUCH_NICK,
1580 3, nick, strlen(nick));
1582 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1583 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1584 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1585 2, idp->data, idp->len);
1586 silc_buffer_free(idp);
1591 /* Check that all mandatory fields are present and request those data
1592 from the server who owns the client if necessary. */
1593 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1598 /* Send the command reply */
1599 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1602 if (client_id_count) {
1603 for (i = 0; i < client_id_count; i++)
1604 silc_free(client_id[i]);
1605 silc_free(client_id);
1612 silc_free(server_name);
1617 SILC_SERVER_CMD_FUNC(identify)
1619 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1622 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1624 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1625 ret = silc_server_command_identify_from_client(cmd);
1626 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1627 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1628 ret = silc_server_command_identify_from_server(cmd);
1631 silc_server_command_free(cmd);
1634 /* Checks string for bad characters and returns TRUE if they are found. */
1636 static int silc_server_command_bad_chars(char *nick)
1638 if (strchr(nick, '\\')) return TRUE;
1639 if (strchr(nick, '\"')) return TRUE;
1640 if (strchr(nick, '´')) return TRUE;
1641 if (strchr(nick, '`')) return TRUE;
1642 if (strchr(nick, '\'')) return TRUE;
1643 if (strchr(nick, '*')) return TRUE;
1644 if (strchr(nick, '/')) return TRUE;
1645 if (strchr(nick, '@')) return TRUE;
1650 /* Server side of command NICK. Sets nickname for user. Setting
1651 nickname causes generation of a new client ID for the client. The
1652 new client ID is sent to the client after changing the nickname. */
1654 SILC_SERVER_CMD_FUNC(nick)
1656 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1657 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1658 SilcServer server = cmd->server;
1659 SilcBuffer packet, nidp, oidp;
1660 SilcClientID *new_id;
1663 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1666 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1668 /* Check nickname */
1669 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1670 if (silc_server_command_bad_chars(nick) == TRUE) {
1671 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1672 SILC_STATUS_ERR_BAD_NICKNAME);
1676 if (strlen(nick) > 128)
1679 /* Create new Client ID */
1680 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1681 cmd->server->md5hash, nick,
1684 /* Send notify about nickname change to our router. We send the new
1685 ID and ask to replace it with the old one. If we are router the
1686 packet is broadcasted. Send NICK_CHANGE notify. */
1687 if (!server->standalone)
1688 silc_server_send_notify_nick_change(server, server->router->connection,
1689 server->server_type == SILC_SERVER ?
1690 FALSE : TRUE, client->id,
1691 new_id, SILC_ID_CLIENT_LEN);
1693 /* Remove old cache entry */
1694 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1697 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1701 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1702 silc_free(client->id);
1705 /* Save the nickname as this client is our local client */
1706 if (client->nickname)
1707 silc_free(client->nickname);
1709 client->nickname = strdup(nick);
1710 client->id = new_id;
1712 /* Update client cache */
1713 silc_idcache_add(server->local_list->clients, client->nickname,
1714 SILC_ID_CLIENT, client->id, (void *)client, TRUE, FALSE);
1716 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1718 /* Send NICK_CHANGE notify to the client's channels */
1719 silc_server_send_notify_on_channels(server, client,
1720 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1721 oidp->data, oidp->len,
1722 nidp->data, nidp->len);
1724 /* Send the new Client ID as reply command back to client */
1725 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1726 SILC_STATUS_OK, 0, 1,
1727 2, nidp->data, nidp->len);
1728 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1729 0, packet->data, packet->len, FALSE);
1731 silc_buffer_free(packet);
1732 silc_buffer_free(nidp);
1733 silc_buffer_free(oidp);
1736 silc_server_command_free(cmd);
1739 SILC_SERVER_CMD_FUNC(list)
1743 /* Server side of TOPIC command. Sets topic for channel and/or returns
1744 current topic to client. */
1746 SILC_SERVER_CMD_FUNC(topic)
1748 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1749 SilcServer server = cmd->server;
1750 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1751 SilcChannelID *channel_id;
1752 SilcChannelEntry channel;
1753 SilcChannelClientEntry chl;
1754 SilcBuffer packet, idp;
1756 unsigned int argc, tmp_len;
1758 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1760 argc = silc_argument_get_arg_num(cmd->args);
1762 /* Get Channel ID */
1763 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1766 SILC_STATUS_ERR_NO_CHANNEL_ID);
1769 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1771 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1772 SILC_STATUS_ERR_NO_CHANNEL_ID);
1776 /* Check whether the channel exists */
1777 channel = silc_idlist_find_channel_by_id(server->local_list,
1780 channel = silc_idlist_find_channel_by_id(server->global_list,
1783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1784 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1791 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1793 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1794 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1798 if (strlen(tmp) > 256) {
1799 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1800 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1804 /* See whether has rights to change topic */
1805 silc_list_start(channel->user_list);
1806 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1807 if (chl->client == client)
1810 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1811 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1813 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1818 /* Set the topic for channel */
1820 silc_free(channel->topic);
1821 channel->topic = strdup(tmp);
1823 /* Send TOPIC_SET notify type to the network */
1824 if (!server->standalone)
1825 silc_server_send_notify_topic_set(server, server->router->connection,
1826 server->server_type == SILC_ROUTER ?
1827 TRUE : FALSE, channel, client->id,
1828 SILC_ID_CLIENT_LEN, channel->topic);
1830 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1832 /* Send notify about topic change to all clients on the channel */
1833 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1834 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1835 idp->data, idp->len,
1836 channel->topic, strlen(channel->topic));
1837 silc_buffer_free(idp);
1840 /* Send the topic to client as reply packet */
1841 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1843 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1844 SILC_STATUS_OK, 0, 2,
1845 2, idp->data, idp->len,
1847 strlen(channel->topic));
1849 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1850 SILC_STATUS_OK, 0, 1,
1851 2, idp->data, idp->len);
1852 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1853 0, packet->data, packet->len, FALSE);
1855 silc_buffer_free(packet);
1856 silc_buffer_free(idp);
1857 silc_free(channel_id);
1860 silc_server_command_free(cmd);
1863 /* Server side of INVITE command. Invites some client to join some channel. */
1865 SILC_SERVER_CMD_FUNC(invite)
1867 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1868 SilcServer server = cmd->server;
1869 SilcSocketConnection sock = cmd->sock, dest_sock;
1870 SilcClientEntry sender, dest;
1871 SilcClientID *dest_id;
1872 SilcChannelEntry channel;
1873 SilcChannelID *channel_id;
1878 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1880 /* Get destination ID */
1881 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1883 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1884 SILC_STATUS_ERR_NO_CLIENT_ID);
1887 dest_id = silc_id_payload_parse_id(tmp, len);
1889 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1890 SILC_STATUS_ERR_NO_CLIENT_ID);
1894 /* Get Channel ID */
1895 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1898 SILC_STATUS_ERR_NO_CHANNEL_ID);
1901 channel_id = silc_id_payload_parse_id(tmp, len);
1903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1904 SILC_STATUS_ERR_NO_CHANNEL_ID);
1908 /* Check whether the channel exists */
1909 channel = silc_idlist_find_channel_by_id(server->local_list,
1912 channel = silc_idlist_find_channel_by_id(server->global_list,
1915 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1916 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1921 /* Check whether the sender of this command is on the channel. */
1922 sender = (SilcClientEntry)sock->user_data;
1923 if (!silc_server_client_on_channel(sender, channel)) {
1924 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1925 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1929 /* Check whether the channel is invite-only channel. If yes then the
1930 sender of this command must be at least channel operator. */
1931 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1932 SilcChannelClientEntry chl;
1934 silc_list_start(channel->user_list);
1935 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1936 if (chl->client == sender) {
1937 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1938 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1939 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1946 /* Find the connection data for the destination. If it is local we will
1947 send it directly otherwise we will send it to router for routing. */
1948 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1950 dest_sock = (SilcSocketConnection)dest->connection;
1952 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1954 /* Check whether the requested client is already on the channel. */
1955 /* XXX if we are normal server we don't know about global clients on
1956 the channel thus we must request it (USERS command), check from
1957 local cache as well. */
1958 if (silc_server_client_on_channel(dest, channel)) {
1959 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1960 SILC_STATUS_ERR_USER_ON_CHANNEL);
1964 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1966 /* Send notify to the client that is invited to the channel */
1967 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1969 SILC_NOTIFY_TYPE_INVITE, 2,
1970 sidp->data, sidp->len, tmp, len);
1972 /* Send command reply */
1973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1976 silc_buffer_free(sidp);
1979 silc_server_command_free(cmd);
1984 SilcSocketConnection sock;
1988 /* Quits connection to client. This gets called if client won't
1989 close the connection even when it has issued QUIT command. */
1991 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1993 QuitInternal q = (QuitInternal)context;
1995 /* Free all client specific data, such as client entry and entires
1996 on channels this client may be on. */
1997 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1999 q->sock->user_data = NULL;
2001 /* Close the connection on our side */
2002 silc_server_close_connection(q->server, q->sock);
2004 silc_free(q->signoff);
2008 /* Quits SILC session. This is the normal way to disconnect client. */
2010 SILC_SERVER_CMD_FUNC(quit)
2012 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2013 SilcServer server = cmd->server;
2014 SilcSocketConnection sock = cmd->sock;
2016 unsigned char *tmp = NULL;
2017 unsigned int len = 0;
2019 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2021 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2024 /* Get destination ID */
2025 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2029 q = silc_calloc(1, sizeof(*q));
2032 q->signoff = tmp ? strdup(tmp) : NULL;
2034 /* We quit the connection with little timeout */
2035 silc_task_register(server->timeout_queue, sock->sock,
2036 silc_server_command_quit_cb, (void *)q,
2037 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2040 silc_server_command_free(cmd);
2043 SILC_SERVER_CMD_FUNC(kill)
2047 /* Server side of command INFO. This sends information about us to
2048 the client. If client requested specific server we will send the
2049 command to that server. */
2051 SILC_SERVER_CMD_FUNC(info)
2053 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2054 SilcServer server = cmd->server;
2055 SilcBuffer packet, idp;
2056 char info_string[256], *dest_server;
2058 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
2060 /* Get server name */
2061 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2063 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2064 SILC_STATUS_ERR_NO_SUCH_SERVER);
2068 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2069 /* Send our reply */
2070 memset(info_string, 0, sizeof(info_string));
2071 snprintf(info_string, sizeof(info_string),
2072 "location: %s server: %s admin: %s <%s>",
2073 server->config->admin_info->location,
2074 server->config->admin_info->server_type,
2075 server->config->admin_info->admin_name,
2076 server->config->admin_info->admin_email);
2078 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2080 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2081 SILC_STATUS_OK, 0, 2,
2082 2, idp->data, idp->len,
2084 strlen(info_string));
2085 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2086 packet->data, packet->len, FALSE);
2088 silc_buffer_free(packet);
2089 silc_buffer_free(idp);
2091 /* Send this command to the requested server */
2093 if (server->server_type == SILC_SERVER && !server->standalone) {
2097 if (server->server_type == SILC_ROUTER) {
2103 silc_server_command_free(cmd);
2106 /* Server side of command PING. This just replies to the ping. */
2108 SILC_SERVER_CMD_FUNC(ping)
2110 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2111 SilcServer server = cmd->server;
2116 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2119 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2122 SILC_STATUS_ERR_NO_SERVER_ID);
2125 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2129 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2130 /* Send our reply */
2131 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2134 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2135 SILC_STATUS_ERR_NO_SUCH_SERVER);
2142 silc_server_command_free(cmd);
2145 /* Internal routine to join channel. The channel sent to this function
2146 has been either created or resolved from ID lists. This joins the sent
2147 client to the channel. */
2149 static void silc_server_command_join_channel(SilcServer server,
2150 SilcServerCommandContext cmd,
2151 SilcChannelEntry channel,
2152 SilcClientID *client_id,
2156 SilcSocketConnection sock = cmd->sock;
2158 unsigned int tmp_len, user_count;
2159 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2160 SilcClientEntry client;
2161 SilcChannelClientEntry chl;
2162 SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
2163 unsigned short ident = silc_command_get_ident(cmd->payload);
2165 SILC_LOG_DEBUG(("Start"));
2170 /* Get passphrase */
2171 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2173 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2174 memcpy(passphrase, tmp, tmp_len);
2178 * Check channel modes
2181 /* Check invite list if channel is invite-only channel */
2182 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2183 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2184 /* Invite list is specified. Check whether client is invited in the
2185 list. If not, then check whether it has been invited otherwise. */
2188 /* XXX client must be invited to be able to join the channel */
2192 /* Check ban list if set */
2193 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2197 /* Check the channel passphrase if set. */
2198 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2199 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
2200 strlen(channel->mode_data.passphrase))) {
2201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2202 SILC_STATUS_ERR_BAD_PASSWORD);
2207 /* Check user count limit if set. */
2208 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2209 if (silc_list_count(channel->user_list) + 1 >
2210 channel->mode_data.user_limit) {
2211 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2212 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2218 * Client is allowed to join to the channel. Make it happen.
2221 /* Get the client entry */
2222 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2223 client = (SilcClientEntry)sock->user_data;
2225 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2228 /* XXX actually this is useless since router finds always cell's
2229 local clients from its local lists. */
2230 client = silc_idlist_find_client_by_id(server->global_list, client_id,
2237 /* Check whether the client already is on the channel */
2238 if (silc_server_client_on_channel(client, channel)) {
2239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2240 SILC_STATUS_ERR_USER_ON_CHANNEL);
2244 /* Generate new channel key as protocol dictates */
2245 if ((!created && silc_list_count(channel->user_list) > 0) ||
2246 !channel->channel_key)
2247 silc_server_create_channel_key(server, channel, 0);
2249 /* Send the channel key. This is broadcasted to the channel but is not
2250 sent to the client who is joining to the channel. */
2251 silc_server_send_channel_key(server, NULL, channel,
2252 server->server_type == SILC_ROUTER ?
2253 FALSE : !server->standalone);
2255 /* Join the client to the channel by adding it to channel's user list.
2256 Add also the channel to client entry's channels list for fast cross-
2258 chl = silc_calloc(1, sizeof(*chl));
2260 chl->client = client;
2261 chl->channel = channel;
2262 silc_list_add(channel->user_list, chl);
2263 silc_list_add(client->channels, chl);
2265 /* Get users on the channel */
2266 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2269 /* Encode Client ID Payload of the original client who wants to join */
2270 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2272 /* Encode command reply packet */
2273 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2274 SILC_PUT32_MSB(channel->mode, mode);
2275 SILC_PUT32_MSB(created, tmp2);
2276 SILC_PUT32_MSB(user_count, tmp3);
2277 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2278 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2279 strlen(channel->channel_key->
2281 channel->channel_key->cipher->name,
2282 channel->key_len / 8, channel->key);
2284 if (!channel->topic) {
2286 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2287 SILC_STATUS_OK, ident, 9,
2288 2, channel->channel_name,
2289 strlen(channel->channel_name),
2290 3, chidp->data, chidp->len,
2291 4, clidp->data, clidp->len,
2294 7, keyp->data, keyp->len,
2296 13, user_list->data, user_list->len,
2297 14, mode_list->data,
2301 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2302 SILC_STATUS_OK, ident, 10,
2303 2, channel->channel_name,
2304 strlen(channel->channel_name),
2305 3, chidp->data, chidp->len,
2306 4, clidp->data, clidp->len,
2309 7, keyp->data, keyp->len,
2311 strlen(channel->topic),
2313 13, user_list->data, user_list->len,
2314 14, mode_list->data,
2318 /* Send command reply */
2319 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2320 reply->data, reply->len, FALSE);
2322 if (!cmd->pending) {
2323 /* Send JOIN notify to locally connected clients on the channel */
2324 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2325 SILC_NOTIFY_TYPE_JOIN, 2,
2326 clidp->data, clidp->len,
2327 chidp->data, chidp->len);
2329 /* Send JOIN notify packet to our primary router */
2330 if (!server->standalone)
2331 silc_server_send_notify_join(server, server->router->connection,
2332 server->server_type == SILC_ROUTER ?
2333 TRUE : FALSE, channel, client->id,
2334 SILC_ID_CLIENT_LEN);
2337 silc_buffer_free(reply);
2338 silc_buffer_free(clidp);
2339 silc_buffer_free(chidp);
2340 silc_buffer_free(keyp);
2341 silc_buffer_free(user_list);
2342 silc_buffer_free(mode_list);
2346 silc_free(passphrase);
2349 /* Server side of command JOIN. Joins client into requested channel. If
2350 the channel does not exist it will be created. */
2352 SILC_SERVER_CMD_FUNC(join)
2354 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2355 SilcServer server = cmd->server;
2357 char *tmp, *channel_name = NULL, *cipher, *hmac;
2358 SilcChannelEntry channel;
2359 unsigned int umode = 0;
2360 int created = FALSE;
2361 SilcClientID *client_id;
2363 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2365 /* Get channel name */
2366 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2369 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2374 if (strlen(channel_name) > 256)
2375 channel_name[255] = '\0';
2377 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2378 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2379 SILC_STATUS_ERR_BAD_CHANNEL);
2380 silc_free(channel_name);
2384 /* Get Client ID of the client who is joining to the channel */
2385 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2388 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2391 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2393 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2394 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2398 /* Get cipher and hmac name */
2399 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2400 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2402 /* See if the channel exists */
2403 channel = silc_idlist_find_channel_by_name(server->local_list,
2404 channel_name, NULL);
2406 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2407 /* If this is coming from client the Client ID in the command packet must
2408 be same as the client's ID. */
2409 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2410 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2411 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2413 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2419 /* Channel not found */
2421 /* If we are standalone server we don't have a router, we just create
2422 the channel by ourselves. */
2423 if (server->standalone) {
2424 channel = silc_server_create_new_channel(server, server->id, cipher,
2425 hmac, channel_name, TRUE);
2426 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2431 /* The channel does not exist on our server. If we are normal server
2432 we will send JOIN command to our router which will handle the
2433 joining procedure (either creates the channel if it doesn't exist
2434 or joins the client to it). */
2435 if (server->server_type == SILC_SERVER) {
2437 unsigned short old_ident;
2439 old_ident = silc_command_get_ident(cmd->payload);
2440 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2441 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2443 /* Send JOIN command to our router */
2444 silc_server_packet_send(server, (SilcSocketConnection)
2445 server->router->connection,
2446 SILC_PACKET_COMMAND, cmd->packet->flags,
2447 tmpbuf->data, tmpbuf->len, TRUE);
2449 /* Reprocess this packet after received reply from router */
2450 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2451 silc_command_get_ident(cmd->payload),
2452 silc_server_command_destructor,
2453 silc_server_command_join,
2454 silc_server_command_dup(cmd));
2455 cmd->pending = TRUE;
2459 /* We are router and the channel does not seem exist so we will check
2460 our global list as well for the channel. */
2461 channel = silc_idlist_find_channel_by_name(server->global_list,
2462 channel_name, NULL);
2464 /* Channel really does not exist, create it */
2465 channel = silc_server_create_new_channel(server, server->id, cipher,
2466 hmac, channel_name, TRUE);
2467 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2474 /* Channel not found */
2476 /* If the command came from router and/or we are normal server then
2477 something went wrong with the joining as the channel was not found.
2478 We can't do anything else but ignore this. */
2479 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2480 server->server_type == SILC_SERVER)
2483 /* We are router and the channel does not seem exist so we will check
2484 our global list as well for the channel. */
2485 channel = silc_idlist_find_channel_by_name(server->global_list,
2486 channel_name, NULL);
2488 /* Channel really does not exist, create it */
2489 channel = silc_server_create_new_channel(server, server->id, cipher,
2490 hmac, channel_name, TRUE);
2491 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2497 /* If the channel does not have global users and is also empty it means the
2498 channel was created globally (by our router) and the client will be the
2499 channel founder and operator. */
2500 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2501 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2502 created = TRUE; /* Created globally by our router */
2505 /* Join to the channel */
2506 silc_server_command_join_channel(server, cmd, channel, client_id,
2509 silc_free(client_id);
2512 silc_server_command_free(cmd);
2515 /* Server side of command MOTD. Sends server's current "message of the
2516 day" to the client. */
2518 SILC_SERVER_CMD_FUNC(motd)
2520 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2521 SilcServer server = cmd->server;
2525 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2527 /* XXX show currently only our motd */
2529 if (server->config && server->config->motd &&
2530 server->config->motd->motd_file) {
2533 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2538 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2544 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2549 silc_server_command_free(cmd);
2552 SILC_SERVER_CMD_FUNC(umode)
2556 /* Checks that client has rights to add or remove channel modes. If any
2557 of the checks fails FALSE is returned. */
2559 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2560 SilcChannelClientEntry client,
2563 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2564 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2566 /* Check whether has rights to change anything */
2567 if (!is_op && !is_fo)
2570 /* Check whether has rights to change everything */
2574 /* We know that client is channel operator, check that they are not
2575 changing anything that requires channel founder rights. Rest of the
2576 modes are available automatically for channel operator. */
2578 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2579 if (is_op && !is_fo)
2582 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2583 if (is_op && !is_fo)
2588 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2589 if (is_op && !is_fo)
2592 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2593 if (is_op && !is_fo)
2598 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2599 if (is_op && !is_fo)
2602 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2603 if (is_op && !is_fo)
2611 /* Server side command of CMODE. Changes channel mode */
2613 SILC_SERVER_CMD_FUNC(cmode)
2615 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2616 SilcServer server = cmd->server;
2617 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2618 SilcChannelID *channel_id;
2619 SilcChannelEntry channel;
2620 SilcChannelClientEntry chl;
2621 SilcBuffer packet, cidp;
2622 unsigned char *tmp, *tmp_id, *tmp_mask;
2623 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2625 SILC_LOG_DEBUG(("Start"));
2627 argc = silc_argument_get_arg_num(cmd->args);
2629 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2630 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2634 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2635 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2639 /* Get Channel ID */
2640 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2642 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2643 SILC_STATUS_ERR_NO_CHANNEL_ID);
2646 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2648 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2649 SILC_STATUS_ERR_NO_CHANNEL_ID);
2653 /* Get the channel mode mask */
2654 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2656 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2657 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2660 SILC_GET32_MSB(mode_mask, tmp_mask);
2662 /* Get channel entry */
2663 channel = silc_idlist_find_channel_by_id(server->local_list,
2666 channel = silc_idlist_find_channel_by_id(server->global_list,
2669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2670 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2675 /* Check whether this client is on the channel */
2676 if (!silc_server_client_on_channel(client, channel)) {
2677 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2678 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2682 /* Get entry to the channel user list */
2683 silc_list_start(channel->user_list);
2684 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2685 if (chl->client == client)
2688 /* Check that client has rights to change any requested channel modes */
2689 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2691 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2696 * Check the modes. Modes that requires nothing special operation are
2700 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2701 /* Channel uses private keys to protect traffic. Client(s) has set the
2702 key locally they want to use, server does not know that key. */
2703 /* Nothing interesting to do here now */
2705 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2706 /* The mode is removed and we need to generate and distribute
2707 new channel key. Clients are not using private channel keys
2708 anymore after this. */
2710 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2713 /* Re-generate channel key */
2714 silc_server_create_channel_key(server, channel, 0);
2716 /* Encode channel key payload to be distributed on the channel */
2718 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2719 strlen(channel->channel_key->
2721 channel->channel_key->cipher->name,
2722 channel->key_len / 8, channel->key);
2724 /* If we are normal server then we will send it to our router. If we
2725 are router we will send it to all local servers that has clients on
2727 if (server->server_type == SILC_SERVER) {
2728 if (!server->standalone)
2729 silc_server_packet_send(server,
2730 cmd->server->router->connection,
2731 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2737 /* Send to locally connected clients on the channel */
2738 silc_server_packet_send_local_channel(server, channel,
2739 SILC_PACKET_CHANNEL_KEY, 0,
2740 packet->data, packet->len, FALSE);
2741 silc_buffer_free(packet);
2745 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2746 /* User limit is set on channel */
2747 unsigned int user_limit;
2749 /* Get user limit */
2750 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2752 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2754 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2758 SILC_GET32_MSB(user_limit, tmp);
2759 channel->mode_data.user_limit = user_limit;
2762 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2763 /* User limit mode is unset. Remove user limit */
2764 channel->mode_data.user_limit = 0;
2767 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2768 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2769 /* Passphrase has been set to channel */
2771 /* Get the passphrase */
2772 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2774 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2775 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2779 /* Save the passphrase */
2780 channel->mode_data.passphrase = strdup(tmp);
2783 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2784 /* Passphrase mode is unset. remove the passphrase */
2785 if (channel->mode_data.passphrase) {
2786 silc_free(channel->mode_data.passphrase);
2787 channel->mode_data.passphrase = NULL;
2792 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2793 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2794 /* Ban list is specified for channel */
2797 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2799 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2800 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2804 /* XXX check that channel founder is not banned */
2806 /* Save the ban list */
2807 channel->mode_data.ban_list = strdup(tmp);
2810 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2811 /* Ban mode is unset. Remove the entire ban list */
2812 if (channel->mode_data.ban_list) {
2813 silc_free(channel->mode_data.ban_list);
2814 channel->mode_data.ban_list = NULL;
2819 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2820 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2821 /* Invite list is specified for channel */
2823 /* Get invite list */
2824 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2827 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2831 /* Save the invite linst */
2832 channel->mode_data.invite_list = strdup(tmp);
2835 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2836 /* Invite list mode is unset. Remove the entire invite list */
2837 if (channel->mode_data.invite_list) {
2838 silc_free(channel->mode_data.invite_list);
2839 channel->mode_data.invite_list = NULL;
2844 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2845 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2846 /* Cipher to use protect the traffic */
2847 unsigned int key_len;
2850 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2852 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2853 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2857 /* XXX Duplicated code, make own function for this!! */
2859 /* Delete old cipher and allocate the new one */
2860 silc_cipher_free(channel->channel_key);
2861 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
2862 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2863 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2866 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
2868 /* Re-generate channel key */
2869 silc_server_create_channel_key(server, channel, key_len);
2871 /* Encode channel key payload to be distributed on the channel */
2873 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2874 strlen(channel->channel_key->
2876 channel->channel_key->cipher->name,
2877 channel->key_len / 8, channel->key);
2879 /* If we are normal server then we will send it to our router. If we
2880 are router we will send it to all local servers that has clients on
2882 if (server->server_type == SILC_SERVER) {
2883 if (!server->standalone)
2884 silc_server_packet_send(server,
2885 cmd->server->router->connection,
2886 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2892 /* Send to locally connected clients on the channel */
2893 silc_server_packet_send_local_channel(server, channel,
2894 SILC_PACKET_CHANNEL_KEY, 0,
2895 packet->data, packet->len, FALSE);
2896 silc_buffer_free(packet);
2899 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2900 /* Cipher mode is unset. Remove the cipher and revert back to
2903 if (channel->mode_data.cipher) {
2904 silc_free(channel->mode_data.cipher);
2905 channel->mode_data.cipher = NULL;
2906 channel->mode_data.key_len = 0;
2909 /* Generate new cipher and key for the channel */
2911 /* XXX Duplicated code, make own function for this!! */
2913 /* Delete old cipher and allocate default one */
2914 silc_cipher_free(channel->channel_key);
2915 if (!channel->cipher)
2916 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
2918 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
2919 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2920 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2925 /* Re-generate channel key */
2926 silc_server_create_channel_key(server, channel, 0);
2928 /* Encode channel key payload to be distributed on the channel */
2930 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2931 strlen(channel->channel_key->
2933 channel->channel_key->cipher->name,
2934 channel->key_len / 8, channel->key);
2936 /* If we are normal server then we will send it to our router. If we
2937 are router we will send it to all local servers that has clients on
2939 if (server->server_type == SILC_SERVER) {
2940 if (!server->standalone)
2941 silc_server_packet_send(server,
2942 cmd->server->router->connection,
2943 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2949 /* Send to locally connected clients on the channel */
2950 silc_server_packet_send_local_channel(server, channel,
2951 SILC_PACKET_CHANNEL_KEY, 0,
2952 packet->data, packet->len, FALSE);
2953 silc_buffer_free(packet);
2957 /* Finally, set the mode */
2958 channel->mode = mode_mask;
2960 /* Send CMODE_CHANGE notify */
2961 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2962 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2963 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2964 cidp->data, cidp->len,
2967 /* Set CMODE notify type to network */
2968 if (!server->standalone)
2969 silc_server_send_notify_cmode(server, server->router->connection,
2970 server->server_type == SILC_ROUTER ?
2971 TRUE : FALSE, channel,
2972 mode_mask, client->id, SILC_ID_CLIENT_LEN);
2974 /* Send command reply to sender */
2975 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2976 SILC_STATUS_OK, 0, 1,
2978 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2979 packet->data, packet->len, FALSE);
2981 silc_buffer_free(packet);
2982 silc_free(channel_id);
2986 silc_server_command_free(cmd);
2989 /* Server side of CUMODE command. Changes client's mode on a channel. */
2991 SILC_SERVER_CMD_FUNC(cumode)
2993 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2994 SilcServer server = cmd->server;
2995 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2996 SilcChannelID *channel_id;
2997 SilcClientID *client_id;
2998 SilcChannelEntry channel;
2999 SilcClientEntry target_client;
3000 SilcChannelClientEntry chl;
3001 SilcBuffer packet, idp;
3002 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3003 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3006 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3008 /* Get Channel ID */
3009 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3011 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3012 SILC_STATUS_ERR_NO_CHANNEL_ID);
3015 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3018 SILC_STATUS_ERR_NO_CHANNEL_ID);
3022 /* Get channel entry */
3023 channel = silc_idlist_find_channel_by_id(server->local_list,
3026 channel = silc_idlist_find_channel_by_id(server->global_list,
3029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3030 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3035 /* Check whether sender is on the channel */
3036 if (!silc_server_client_on_channel(client, channel)) {
3037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3038 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3042 /* Check that client has rights to change other's rights */
3043 silc_list_start(channel->user_list);
3044 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3045 if (chl->client == client) {
3046 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3047 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3048 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3049 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3053 sender_mask = chl->mode;
3058 /* Get the target client's channel mode mask */
3059 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3061 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3062 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3065 SILC_GET32_MSB(target_mask, tmp_mask);
3067 /* Get target Client ID */
3068 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3070 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3071 SILC_STATUS_ERR_NO_CLIENT_ID);
3074 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3076 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3077 SILC_STATUS_ERR_NO_CLIENT_ID);
3081 /* Get target client's entry */
3082 target_client = silc_idlist_find_client_by_id(server->local_list,
3084 if (!target_client) {
3085 target_client = silc_idlist_find_client_by_id(server->global_list,
3089 /* Check whether target client is on the channel */
3090 if (!silc_server_client_on_channel(target_client, channel)) {
3091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3092 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3096 /* Get entry to the channel user list */
3097 silc_list_start(channel->user_list);
3098 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3099 if (chl->client == target_client)
3106 /* If the target client is founder, no one else can change their mode
3108 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3110 SILC_STATUS_ERR_NOT_YOU);
3114 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3115 /* Cannot promote anyone to channel founder */
3116 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3117 SILC_STATUS_ERR_NOT_YOU);
3120 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3121 if (target_client == client) {
3122 /* Remove channel founder rights from itself */
3123 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3127 SILC_STATUS_ERR_NOT_YOU);
3133 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3134 /* Promote to operator */
3135 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3136 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3140 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3141 /* Demote to normal user */
3142 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3147 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3149 /* Send notify to channel, notify only if mode was actually changed. */
3151 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3152 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3153 idp->data, idp->len,
3157 /* Set CUMODE notify type to network */
3158 if (!server->standalone)
3159 silc_server_send_notify_cumode(server, server->router->connection,
3160 server->server_type == SILC_ROUTER ?
3161 TRUE : FALSE, channel,
3162 target_mask, client->id,
3165 SILC_ID_CLIENT_LEN);
3168 /* Send command reply to sender */
3169 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3170 SILC_STATUS_OK, 0, 2,
3172 3, tmp_id, tmp_len);
3173 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3174 packet->data, packet->len, FALSE);
3176 silc_buffer_free(packet);
3177 silc_free(channel_id);
3178 silc_free(client_id);
3179 silc_buffer_free(idp);
3182 silc_server_command_free(cmd);
3185 /* Server side of KICK command. Kicks client out of channel. */
3187 SILC_SERVER_CMD_FUNC(kick)
3189 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3190 SilcServer server = cmd->server;
3191 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3192 SilcClientEntry target_client;
3193 SilcChannelID *channel_id;
3194 SilcClientID *client_id;
3195 SilcChannelEntry channel;
3196 SilcChannelClientEntry chl;
3198 unsigned int tmp_len;
3199 unsigned char *tmp, *comment;
3201 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3203 /* Get Channel ID */
3204 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3206 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3207 SILC_STATUS_ERR_NO_CHANNEL_ID);
3210 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3213 SILC_STATUS_ERR_NO_CHANNEL_ID);
3217 /* Get channel entry */
3218 channel = silc_idlist_find_channel_by_id(server->local_list,
3221 channel = silc_idlist_find_channel_by_id(server->local_list,
3224 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3225 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3230 /* Check whether sender is on the channel */
3231 if (!silc_server_client_on_channel(client, channel)) {
3232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3233 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3237 /* Check that the kicker is channel operator or channel founder */
3238 silc_list_start(channel->user_list);
3239 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3240 if (chl->client == client) {
3241 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3243 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3250 /* Get target Client ID */
3251 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3253 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3254 SILC_STATUS_ERR_NO_CLIENT_ID);
3257 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3259 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3260 SILC_STATUS_ERR_NO_CLIENT_ID);
3264 /* Get target client's entry */
3265 target_client = silc_idlist_find_client_by_id(server->local_list,
3267 if (!target_client) {
3268 target_client = silc_idlist_find_client_by_id(server->global_list,
3272 /* Check that the target client is not channel founder. Channel founder
3273 cannot be kicked from the channel. */
3274 silc_list_start(channel->user_list);
3275 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3276 if (chl->client == target_client) {
3277 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3279 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3286 /* Check whether target client is on the channel */
3287 if (!silc_server_client_on_channel(target_client, channel)) {
3288 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3289 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3295 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3299 /* Send command reply to sender */
3300 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3303 /* Send KICKED notify to local clients on the channel */
3304 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3305 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3306 SILC_NOTIFY_TYPE_KICKED,
3308 idp->data, idp->len,
3309 comment, comment ? strlen(comment) : 0);
3310 silc_buffer_free(idp);
3312 /* Remove the client from the channel. If the channel does not exist
3313 after removing the client then the client kicked itself of the channel
3314 and we don't have to send anything after that. */
3315 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3316 target_client, FALSE))
3319 /* Send KICKED notify to primary route */
3320 if (!server->standalone)
3321 silc_server_send_notify_kicked(server, server->router->connection,
3322 server->server_type == SILC_ROUTER ?
3323 TRUE : FALSE, channel,
3324 target_client->id, SILC_ID_CLIENT_LEN,
3327 /* Re-generate channel key */
3328 silc_server_create_channel_key(server, channel, 0);
3330 /* Send the channel key to the channel. The key of course is not sent
3331 to the client who joined the channel. */
3332 silc_server_send_channel_key(server, target_client->connection, channel,
3333 server->server_type == SILC_ROUTER ?
3334 FALSE : !server->standalone);
3337 silc_server_command_free(cmd);
3340 SILC_SERVER_CMD_FUNC(oper)
3344 SILC_SERVER_CMD_FUNC(silcoper)
3348 /* Server side command of CONNECT. Connects us to the specified remote
3349 server or router. */
3351 SILC_SERVER_CMD_FUNC(connect)
3353 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3354 SilcServer server = cmd->server;
3355 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3357 unsigned int tmp_len;
3358 unsigned int port = SILC_PORT;
3360 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
3362 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3365 /* Check whether client has the permissions. */
3366 if (client->mode == SILC_UMODE_NONE) {
3367 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3368 SILC_STATUS_ERR_NO_SERVER_PRIV);
3372 if (server->server_type == SILC_ROUTER &&
3373 client->mode & SILC_UMODE_SERVER_OPERATOR) {
3374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3375 SILC_STATUS_ERR_NO_ROUTER_PRIV);
3379 /* Get the remote server */
3380 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3383 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3388 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3390 SILC_GET32_MSB(port, tmp);
3392 /* Create the connection. It is done with timeout and is async. */
3393 silc_server_create_connection(server, tmp, port);
3395 /* Send reply to the sender */
3396 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3400 silc_server_command_free(cmd);
3403 SILC_SERVER_CMD_FUNC(restart)
3407 /* Server side command of CLOSE. Closes connection to a specified server. */
3409 SILC_SERVER_CMD_FUNC(close)
3411 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3412 SilcServer server = cmd->server;
3413 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3414 SilcServerEntry server_entry;
3416 unsigned int tmp_len;
3417 unsigned char *name;
3418 unsigned int port = SILC_PORT;
3420 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3422 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3425 /* Check whether client has the permissions. */
3426 if (client->mode == SILC_UMODE_NONE) {
3427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3428 SILC_STATUS_ERR_NO_SERVER_PRIV);
3432 /* Get the remote server */
3433 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3436 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3441 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3443 SILC_GET32_MSB(port, tmp);
3445 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3447 if (!server_entry) {
3448 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3449 SILC_STATUS_ERR_NO_SERVER_ID);
3453 /* Close the connection to the server */
3454 silc_server_free_sock_user_data(server, server_entry->connection);
3455 silc_server_disconnect_remote(server, server_entry->connection,
3456 "Server closed connection: "
3457 "Closed by operator");
3459 /* Send reply to the sender */
3460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3464 silc_server_command_free(cmd);
3467 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3468 active connections. */
3470 SILC_SERVER_CMD_FUNC(shutdown)
3472 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3473 SilcServer server = cmd->server;
3474 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3476 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3478 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3481 /* Check whether client has the permission. */
3482 if (client->mode == SILC_UMODE_NONE) {
3483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3484 SILC_STATUS_ERR_NO_SERVER_PRIV);
3488 /* Then, gracefully, or not, bring the server down. */
3489 silc_server_stop(server);
3491 /* Send reply to the sender */
3492 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3496 silc_server_command_free(cmd);
3499 /* Server side command of LEAVE. Removes client from a channel. */
3501 SILC_SERVER_CMD_FUNC(leave)
3503 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3504 SilcServer server = cmd->server;
3505 SilcSocketConnection sock = cmd->sock;
3506 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3508 SilcChannelEntry channel;
3510 unsigned int i, len;
3513 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3515 /* Get Channel ID */
3516 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3518 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3519 SILC_STATUS_ERR_NO_CHANNEL_ID);
3522 id = silc_id_payload_parse_id(tmp, len);
3524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3525 SILC_STATUS_ERR_NO_CHANNEL_ID);
3529 /* Get channel entry */
3530 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3532 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3534 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3535 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3540 /* Check whether this client is on the channel */
3541 if (!silc_server_client_on_channel(id_entry, channel)) {
3542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3543 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3547 /* Notify routers that they should remove this client from their list
3548 of clients on the channel. Send LEAVE notify type. */
3549 if (!server->standalone)
3550 silc_server_send_notify_leave(server, server->router->connection,
3551 server->server_type == SILC_ROUTER ?
3552 TRUE : FALSE, channel, id_entry->id,
3553 SILC_ID_CLIENT_LEN);
3555 /* Remove client from channel */
3556 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3561 /* If the channel does not exist anymore we won't send anything */
3565 /* Re-generate channel key */
3566 silc_server_create_channel_key(server, channel, 0);
3568 /* Encode channel key payload to be distributed on the channel */
3570 silc_channel_key_payload_encode(len, tmp,
3571 strlen(channel->channel_key->cipher->name),
3572 channel->channel_key->cipher->name,
3573 channel->key_len / 8, channel->key);
3575 /* If we are normal server then we will send it to our router. If we
3576 are router we will send it to all local servers that has clients on
3578 if (server->server_type == SILC_SERVER) {
3579 if (!server->standalone)
3580 silc_server_packet_send(server,
3581 cmd->server->router->connection,
3582 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3583 packet->len, FALSE);
3588 /* Send to locally connected clients on the channel */
3589 silc_server_packet_send_local_channel(server, channel,
3590 SILC_PACKET_CHANNEL_KEY, 0,
3591 packet->data, packet->len, FALSE);
3593 silc_buffer_free(packet);
3597 silc_server_command_free(cmd);
3600 /* Server side of command USERS. Resolves clients and their USERS currently
3601 joined on the requested channel. The list of Client ID's and their modes
3602 on the channel is sent back. */
3604 SILC_SERVER_CMD_FUNC(users)
3606 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3607 SilcServer server = cmd->server;
3608 SilcChannelEntry channel;
3611 unsigned char *channel_id;
3612 unsigned int channel_id_len;
3613 SilcBuffer client_id_list;
3614 SilcBuffer client_mode_list;
3615 unsigned char lc[4];
3616 unsigned int list_count = 0;
3617 unsigned short ident = silc_command_get_ident(cmd->payload);
3619 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3621 /* Get Channel ID */
3622 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3624 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3625 SILC_STATUS_ERR_NO_CHANNEL_ID);
3628 id = silc_id_payload_parse_id(channel_id, channel_id_len);
3630 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3631 SILC_STATUS_ERR_NO_CHANNEL_ID);
3635 /* If we are server and we don't know about this channel we will send
3636 the command to our router. If we know about the channel then we also
3637 have the list of users already. */
3638 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3640 if (server->server_type == SILC_SERVER && !server->standalone &&
3644 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3645 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3647 /* Send USERS command */
3648 silc_server_packet_send(server, server->router->connection,
3649 SILC_PACKET_COMMAND, cmd->packet->flags,
3650 tmpbuf->data, tmpbuf->len, TRUE);
3652 /* Reprocess this packet after received reply */
3653 silc_server_command_pending(server, SILC_COMMAND_USERS,
3654 silc_command_get_ident(cmd->payload),
3655 silc_server_command_destructor,
3656 silc_server_command_users,
3657 silc_server_command_dup(cmd));
3658 cmd->pending = TRUE;
3659 silc_command_set_ident(cmd->payload, ident);
3661 silc_buffer_free(tmpbuf);
3666 /* We are router and we will check the global list as well. */
3667 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3669 /* Channel really does not exist */
3670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3671 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3676 /* Get the users list */
3677 silc_server_get_users_on_channel(server, channel, &client_id_list,
3678 &client_mode_list, &list_count);
3681 SILC_PUT32_MSB(list_count, lc);
3684 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3685 SILC_STATUS_OK, 0, 4,
3686 2, channel_id, channel_id_len,
3688 4, client_id_list->data,
3689 client_id_list->len,
3690 5, client_mode_list->data,
3691 client_mode_list->len);
3692 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3693 packet->data, packet->len, FALSE);
3695 silc_buffer_free(packet);
3696 silc_buffer_free(client_id_list);
3697 silc_buffer_free(client_mode_list);
3701 silc_server_command_free(cmd);