5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
37 unsigned int arg_type,
39 unsigned int arg_len);
40 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
45 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
49 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
50 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
54 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(connect, CONNECT,
56 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
60 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
63 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
65 SILC_SERVER_CMD(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_STRICT | SILC_CF_REG),
74 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
75 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
80 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
82 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
84 SILC_LOG_DEBUG(("Start")); \
87 silc_server_command_send_status_reply(cmd, command, \
88 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
89 silc_server_command_free(cmd); \
93 silc_server_command_send_status_reply(cmd, command, \
94 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
95 silc_server_command_free(cmd); \
100 /* Returns TRUE if the connection is registered. Unregistered connections
101 usually cannot send commands hence the check. */
103 static int silc_server_is_registered(SilcServer server,
104 SilcSocketConnection sock,
105 SilcServerCommandContext cmd,
108 SilcIDListData idata = (SilcIDListData)sock->user_data;
109 if (idata->registered)
112 silc_server_command_send_status_reply(cmd, command,
113 SILC_STATUS_ERR_NOT_REGISTERED);
114 silc_server_command_free(cmd);
118 /* Internal context to hold data when executed command with timeout. */
120 SilcServerCommandContext ctx;
121 SilcServerCommand *cmd;
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 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
132 /* Update access time */
133 client->last_command = time(NULL);
135 if (!(timeout->cmd->flags & SILC_CF_REG))
136 timeout->cmd->cb(timeout->ctx);
137 else if (silc_server_is_registered(timeout->ctx->server,
141 timeout->cmd->cb(timeout->ctx);
146 /* Processes received command packet. */
148 void silc_server_command_process(SilcServer server,
149 SilcSocketConnection sock,
150 SilcPacketContext *packet)
152 SilcServerCommandContext ctx;
153 SilcServerCommand *cmd;
156 /* Allocate command context. This must be free'd by the
157 command routine receiving it. */
158 ctx = silc_server_command_alloc();
159 ctx->server = server;
160 ctx->sock = silc_socket_dup(sock);
161 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
163 /* Parse the command payload in the packet */
164 ctx->payload = silc_command_payload_parse(packet->buffer);
166 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
167 silc_buffer_free(packet->buffer);
168 silc_packet_context_free(packet);
169 silc_socket_free(ctx->sock);
173 ctx->args = silc_command_get_args(ctx->payload);
175 /* Get the command */
176 command = silc_command_get(ctx->payload);
177 for (cmd = silc_command_list; cmd->cb; cmd++)
178 if (cmd->cmd == command)
182 silc_server_command_send_status_reply(ctx, command,
183 SILC_STATUS_ERR_UNKNOWN_COMMAND);
184 silc_server_command_free(ctx);
188 /* Execute client's commands always with timeout. Normally they are
189 executed with zero (0) timeout but if client is sending command more
190 frequently than once in 2 seconds, then the timeout may be 0 to 2
192 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
193 SilcClientEntry client = (SilcClientEntry)sock->user_data;
194 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
200 if (client->last_command && (time(NULL) - client->last_command) < 2) {
201 client->fast_command++;
204 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
205 client->fast_command--);
209 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
210 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
211 silc_task_register(server->timeout_queue, sock->sock,
212 silc_server_command_process_timeout,
214 2 - (time(NULL) - client->last_command), 0,
216 SILC_TASK_PRI_NORMAL);
218 silc_task_register(server->timeout_queue, sock->sock,
219 silc_server_command_process_timeout,
223 SILC_TASK_PRI_NORMAL);
227 /* Execute for server */
229 if (!(cmd->flags & SILC_CF_REG))
231 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
235 /* Allocate Command Context */
237 SilcServerCommandContext silc_server_command_alloc()
239 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
244 /* Free's the command context allocated before executing the command */
246 void silc_server_command_free(SilcServerCommandContext ctx)
249 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
251 if (ctx->users < 1) {
253 silc_command_free_payload(ctx->payload);
255 silc_packet_context_free(ctx->packet);
257 silc_socket_free(ctx->sock); /* Decrease reference counter */
262 /* Duplicate Command Context by adding reference counter. The context won't
263 be free'd untill it hits zero. */
265 SilcServerCommandContext
266 silc_server_command_dup(SilcServerCommandContext ctx)
269 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
274 /* Add new pending command to be executed when reply to a command has been
275 received. The `reply_cmd' is the command that will call the `callback'
276 with `context' when reply has been received. If `ident' is non-zero
277 the `callback' will be executed when received reply with command
278 identifier `ident'. */
280 void silc_server_command_pending(SilcServer server,
281 SilcCommand reply_cmd,
282 unsigned short ident,
283 SilcServerPendingDestructor destructor,
284 SilcCommandCb callback,
287 SilcServerCommandPending *reply;
289 reply = silc_calloc(1, sizeof(*reply));
290 reply->reply_cmd = reply_cmd;
291 reply->ident = ident;
292 reply->context = context;
293 reply->callback = callback;
294 reply->destructor = destructor;
295 silc_dlist_add(server->pending_commands, reply);
298 /* Deletes pending command by reply command type. */
300 void silc_server_command_pending_del(SilcServer server,
301 SilcCommand reply_cmd,
302 unsigned short ident)
304 SilcServerCommandPending *r;
306 silc_dlist_start(server->pending_commands);
307 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
308 if (r->reply_cmd == reply_cmd && r->ident == ident) {
309 silc_dlist_del(server->pending_commands, r);
315 /* Checks for pending commands and marks callbacks to be called from
316 the command reply function. Returns TRUE if there were pending command. */
318 int silc_server_command_pending_check(SilcServer server,
319 SilcServerCommandReplyContext ctx,
321 unsigned short ident)
323 SilcServerCommandPending *r;
325 silc_dlist_start(server->pending_commands);
326 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
327 if (r->reply_cmd == command && r->ident == ident) {
328 ctx->context = r->context;
329 ctx->callback = r->callback;
330 ctx->destructor = r->destructor;
339 /* Destructor function for pending callbacks. This is called when using
340 pending commands to free the context given for the pending command. */
342 static void silc_server_command_destructor(void *context)
344 silc_server_command_free((SilcServerCommandContext)context);
347 /* Sends simple status message as command reply packet */
350 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
352 SilcCommandStatus status)
356 SILC_LOG_DEBUG(("Sending command status %d", status));
359 silc_command_reply_payload_encode_va(command, status,
360 silc_command_get_ident(cmd->payload),
362 silc_server_packet_send(cmd->server, cmd->sock,
363 SILC_PACKET_COMMAND_REPLY, 0,
364 buffer->data, buffer->len, FALSE);
365 silc_buffer_free(buffer);
368 /* Sends command status reply with one extra argument. The argument
369 type must be sent as argument. */
372 silc_server_command_send_status_data(SilcServerCommandContext cmd,
374 SilcCommandStatus status,
375 unsigned int arg_type,
377 unsigned int arg_len)
381 SILC_LOG_DEBUG(("Sending command status %d", status));
384 silc_command_reply_payload_encode_va(command, status,
385 silc_command_get_ident(cmd->payload),
386 1, arg_type, arg, arg_len);
387 silc_server_packet_send(cmd->server, cmd->sock,
388 SILC_PACKET_COMMAND_REPLY, 0,
389 buffer->data, buffer->len, FALSE);
390 silc_buffer_free(buffer);
393 /******************************************************************************
397 ******************************************************************************/
400 silc_server_command_whois_parse(SilcServerCommandContext cmd,
401 SilcClientID ***client_id,
402 unsigned int *client_id_count,
410 unsigned int argc = silc_argument_get_arg_num(cmd->args);
413 /* If client ID is in the command it must be used instead of nickname */
414 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
416 /* No ID, get the nickname@server string and parse it. */
417 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
419 if (strchr(tmp, '@')) {
420 len = strcspn(tmp, "@");
421 *nickname = silc_calloc(len + 1, sizeof(char));
422 memcpy(*nickname, tmp, len);
423 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
424 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
426 *nickname = strdup(tmp);
429 silc_server_command_send_status_reply(cmd, command,
430 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
434 /* Command includes ID, we must use that. Also check whether the command
435 has more than one ID set - take them all. */
437 *client_id = silc_calloc(1, sizeof(**client_id));
438 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
439 if ((*client_id)[0] == NULL) {
440 silc_free(*client_id);
443 *client_id_count = 1;
445 /* Take all ID's from the command packet */
447 for (k = 1, i = 1; i < argc; i++) {
448 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
450 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
451 (*client_id_count + 1));
452 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
453 if ((*client_id)[k] == NULL) {
454 /* Cleanup all and fail */
455 for (i = 0; i < *client_id_count; i++)
456 silc_free((*client_id)[i]);
457 silc_free(*client_id);
460 (*client_id_count)++;
466 /* Command includes ID, use that */
469 /* Get the max count of reply messages allowed */
470 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
480 silc_server_command_whois_check(SilcServerCommandContext cmd,
481 SilcClientEntry *clients,
482 unsigned int clients_count)
484 SilcServer server = cmd->server;
486 SilcClientEntry entry;
488 for (i = 0; i < clients_count; i++) {
491 if (entry->data.registered == FALSE)
494 if (!entry->nickname || !entry->username || !entry->userinfo) {
496 unsigned short old_ident;
501 old_ident = silc_command_get_ident(cmd->payload);
502 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
503 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
505 /* Send WHOIS command */
506 silc_server_packet_send(server, entry->router->connection,
507 SILC_PACKET_COMMAND, cmd->packet->flags,
508 tmpbuf->data, tmpbuf->len, TRUE);
510 /* Reprocess this packet after received reply */
511 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
512 silc_command_get_ident(cmd->payload),
513 silc_server_command_destructor,
514 silc_server_command_whois,
515 silc_server_command_dup(cmd));
518 silc_command_set_ident(cmd->payload, old_ident);
520 silc_buffer_free(tmpbuf);
529 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
530 SilcClientEntry *clients,
531 unsigned int clients_count,
534 SilcServer server = cmd->server;
537 SilcBuffer packet, idp, channels;
538 SilcClientEntry entry;
539 SilcCommandStatus status;
540 unsigned short ident = silc_command_get_ident(cmd->payload);
541 char nh[128], uh[128];
542 unsigned char idle[4], mode[4];
543 SilcSocketConnection hsock;
546 for (i = 0; i < clients_count; i++)
547 if (clients[i]->data.registered)
550 status = SILC_STATUS_OK;
552 status = SILC_STATUS_LIST_START;
554 for (i = 0, k = 0; i < clients_count; i++) {
557 if (entry->data.registered == FALSE) {
558 if (clients_count == 1) {
559 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
560 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
561 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
562 2, idp->data, idp->len);
563 silc_buffer_free(idp);
569 status = SILC_STATUS_LIST_ITEM;
571 if (clients_count > 1 && k == clients_count - 1)
572 status = SILC_STATUS_LIST_END;
574 if (count && k - 1 == count)
575 status = SILC_STATUS_LIST_END;
577 if (count && k - 1 > count)
580 /* Sanity check, however these should never fail. However, as
581 this sanity check has been added here they have failed. */
582 if (!entry->nickname || !entry->username || !entry->userinfo)
585 /* Send WHOIS reply */
586 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
587 tmp = silc_argument_get_first_arg(cmd->args, NULL);
589 memset(uh, 0, sizeof(uh));
590 memset(nh, 0, sizeof(nh));
591 memset(idle, 0, sizeof(idle));
593 strncat(nh, entry->nickname, strlen(entry->nickname));
594 if (!strchr(entry->nickname, '@')) {
596 len = entry->router ? strlen(entry->router->server_name) :
597 strlen(server->server_name);
598 strncat(nh, entry->router ? entry->router->server_name :
599 server->server_name, len);
602 strncat(uh, entry->username, strlen(entry->username));
603 if (!strchr(entry->username, '@')) {
605 hsock = (SilcSocketConnection)entry->connection;
606 len = strlen(hsock->hostname);
607 strncat(uh, hsock->hostname, len);
610 channels = silc_server_get_client_channel_list(server, entry);
612 SILC_PUT32_MSB(entry->mode, mode);
614 if (entry->connection) {
615 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
619 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
621 2, idp->data, idp->len,
625 strlen(entry->userinfo),
631 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
633 2, idp->data, idp->len,
637 strlen(entry->userinfo),
641 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
642 0, packet->data, packet->len, FALSE);
644 silc_buffer_free(packet);
645 silc_buffer_free(idp);
647 silc_buffer_free(channels);
654 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
656 SilcServer server = cmd->server;
657 char *nick = NULL, *server_name = NULL;
658 int count = 0, clients_count = 0;
659 SilcClientEntry *clients = NULL, entry;
660 SilcClientID **client_id = NULL;
661 unsigned int client_id_count = 0;
664 /* Protocol dictates that we must always send the received WHOIS request
665 to our router if we are normal server, so let's do it now unless we
666 are standalone. We will not send any replies to the client until we
667 have received reply from the router. */
668 if (server->server_type == SILC_SERVER && !cmd->pending &&
669 !server->standalone) {
671 unsigned short old_ident;
673 old_ident = silc_command_get_ident(cmd->payload);
674 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
675 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
677 /* Send WHOIS command to our router */
678 silc_server_packet_send(server, (SilcSocketConnection)
679 server->router->connection,
680 SILC_PACKET_COMMAND, cmd->packet->flags,
681 tmpbuf->data, tmpbuf->len, TRUE);
683 /* Reprocess this packet after received reply from router */
684 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
685 silc_command_get_ident(cmd->payload),
686 silc_server_command_destructor,
687 silc_server_command_whois,
688 silc_server_command_dup(cmd));
691 silc_command_set_ident(cmd->payload, old_ident);
693 silc_buffer_free(tmpbuf);
698 /* We are ready to process the command request. Let's search for the
699 requested client and send reply to the requesting client. */
701 /* Parse the whois request */
702 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
703 &nick, &server_name, &count,
707 /* Get all clients matching that ID or nickname from local list */
708 if (client_id_count) {
709 /* Check all Client ID's received in the command packet */
710 for (i = 0; i < client_id_count; i++) {
711 entry = silc_idlist_find_client_by_id(server->local_list,
714 clients = silc_realloc(clients, sizeof(*clients) *
715 (clients_count + 1));
716 clients[clients_count++] = entry;
720 clients = silc_idlist_get_clients_by_hash(server->local_list,
721 nick, server->md5hash,
724 clients = silc_idlist_get_clients_by_nickname(server->local_list,
729 /* Check global list as well */
731 if (client_id_count) {
732 /* Check all Client ID's received in the command packet */
733 for (i = 0; i < client_id_count; i++) {
734 entry = silc_idlist_find_client_by_id(server->global_list,
737 clients = silc_realloc(clients, sizeof(*clients) *
738 (clients_count + 1));
739 clients[clients_count++] = entry;
743 clients = silc_idlist_get_clients_by_hash(server->global_list,
744 nick, server->md5hash,
747 clients = silc_idlist_get_clients_by_nickname(server->global_list,
754 /* Such client(s) really does not exist in the SILC network. */
755 if (!client_id_count) {
756 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
757 SILC_STATUS_ERR_NO_SUCH_NICK,
758 3, nick, strlen(nick));
760 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
761 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
762 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
763 2, idp->data, idp->len);
764 silc_buffer_free(idp);
769 /* Router always finds the client entry if it exists in the SILC network.
770 However, it might be incomplete entry and does not include all the
771 mandatory fields that WHOIS command reply requires. Check for these and
772 make query from the server who owns the client if some fields are
774 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
779 /* Send the command reply to the client */
780 silc_server_command_whois_send_reply(cmd, clients, clients_count,
784 if (client_id_count) {
785 for (i = 0; i < client_id_count; i++)
786 silc_free(client_id[i]);
787 silc_free(client_id);
794 silc_free(server_name);
800 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
802 SilcServer server = cmd->server;
803 char *nick = NULL, *server_name = NULL;
804 int count = 0, clients_count = 0;
805 SilcClientEntry *clients = NULL, entry;
806 SilcClientID **client_id = NULL;
807 unsigned int client_id_count = 0;
810 /* Parse the whois request */
811 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
812 &nick, &server_name, &count,
816 /* Process the command request. Let's search for the requested client and
817 send reply to the requesting server. */
819 if (client_id_count) {
820 /* Check all Client ID's received in the command packet */
821 for (i = 0; i < client_id_count; i++) {
822 entry = silc_idlist_find_client_by_id(server->local_list,
825 clients = silc_realloc(clients, sizeof(*clients) *
826 (clients_count + 1));
827 clients[clients_count++] = entry;
831 clients = silc_idlist_get_clients_by_hash(server->local_list,
832 nick, server->md5hash,
835 clients = silc_idlist_get_clients_by_nickname(server->local_list,
840 /* If we are router we will check our global list as well. */
841 if (!clients && server->server_type == SILC_ROUTER) {
842 if (client_id_count) {
843 /* Check all Client ID's received in the command packet */
844 for (i = 0; i < client_id_count; i++) {
845 entry = silc_idlist_find_client_by_id(server->global_list,
848 clients = silc_realloc(clients, sizeof(*clients) *
849 (clients_count + 1));
850 clients[clients_count++] = entry;
854 clients = silc_idlist_get_clients_by_hash(server->global_list,
855 nick, server->md5hash,
858 clients = silc_idlist_get_clients_by_nickname(server->global_list,
865 /* Such a client really does not exist in the SILC network. */
866 if (!client_id_count) {
867 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
868 SILC_STATUS_ERR_NO_SUCH_NICK,
869 3, nick, strlen(nick));
871 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
872 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
873 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
874 2, idp->data, idp->len);
875 silc_buffer_free(idp);
880 /* Router always finds the client entry if it exists in the SILC network.
881 However, it might be incomplete entry and does not include all the
882 mandatory fields that WHOIS command reply requires. Check for these and
883 make query from the server who owns the client if some fields are
885 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
890 /* Send the command reply to the client */
891 silc_server_command_whois_send_reply(cmd, clients, clients_count,
895 if (client_id_count) {
896 for (i = 0; i < client_id_count; i++)
897 silc_free(client_id[i]);
898 silc_free(client_id);
905 silc_free(server_name);
910 /* Server side of command WHOIS. Processes user's query and sends found
911 results as command replies back to the client. */
913 SILC_SERVER_CMD_FUNC(whois)
915 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
918 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
920 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
921 ret = silc_server_command_whois_from_client(cmd);
922 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
923 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
924 ret = silc_server_command_whois_from_server(cmd);
927 silc_server_command_free(cmd);
930 /******************************************************************************
934 ******************************************************************************/
937 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
945 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
948 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
952 /* Get the nickname@server string and parse it. */
953 if (strchr(tmp, '@')) {
954 len = strcspn(tmp, "@");
955 *nickname = silc_calloc(len + 1, sizeof(char));
956 memcpy(*nickname, tmp, len);
957 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
958 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
960 *nickname = strdup(tmp);
962 /* Get the max count of reply messages allowed */
963 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
973 silc_server_command_whowas_check(SilcServerCommandContext cmd,
974 SilcClientEntry *clients,
975 unsigned int clients_count)
977 SilcServer server = cmd->server;
979 SilcClientEntry entry;
981 for (i = 0; i < clients_count; i++) {
984 if (!entry->nickname || !entry->username) {
986 unsigned short old_ident;
991 old_ident = silc_command_get_ident(cmd->payload);
992 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
993 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
995 /* Send WHOWAS command */
996 silc_server_packet_send(server, entry->router->connection,
997 SILC_PACKET_COMMAND, cmd->packet->flags,
998 tmpbuf->data, tmpbuf->len, TRUE);
1000 /* Reprocess this packet after received reply */
1001 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1002 silc_command_get_ident(cmd->payload),
1003 silc_server_command_destructor,
1004 silc_server_command_whowas,
1005 silc_server_command_dup(cmd));
1006 cmd->pending = TRUE;
1008 silc_command_set_ident(cmd->payload, old_ident);
1010 silc_buffer_free(tmpbuf);
1019 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1020 SilcClientEntry *clients,
1021 unsigned int clients_count)
1023 SilcServer server = cmd->server;
1025 int i, count = 0, len;
1026 SilcBuffer packet, idp;
1027 SilcClientEntry entry = NULL;
1028 SilcCommandStatus status;
1029 unsigned short ident = silc_command_get_ident(cmd->payload);
1031 char nh[256], uh[256];
1033 status = SILC_STATUS_OK;
1034 if (clients_count > 1)
1035 status = SILC_STATUS_LIST_START;
1037 for (i = 0; i < clients_count; i++) {
1040 /* We will take only clients that are not valid anymore. They are the
1041 ones that are not registered anymore but still have a ID. They
1042 have disconnected us, and thus valid for WHOWAS. */
1043 if (entry->data.registered == TRUE)
1045 if (entry->id == NULL)
1048 if (count && i - 1 == count)
1053 if (clients_count > 2)
1054 status = SILC_STATUS_LIST_ITEM;
1056 if (clients_count > 1 && i == clients_count - 1)
1057 status = SILC_STATUS_LIST_END;
1059 /* Sanity check, however these should never fail. However, as
1060 this sanity check has been added here they have failed. */
1061 if (!entry->nickname || !entry->username)
1064 /* Send WHOWAS reply */
1065 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1066 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1068 memset(uh, 0, sizeof(uh));
1069 memset(nh, 0, sizeof(nh));
1071 strncat(nh, entry->nickname, strlen(entry->nickname));
1072 if (!strchr(entry->nickname, '@')) {
1073 strncat(nh, "@", 1);
1074 len = entry->router ? strlen(entry->router->server_name) :
1075 strlen(server->server_name);
1076 strncat(nh, entry->router ? entry->router->server_name :
1077 server->server_name, len);
1080 strncat(uh, entry->username, strlen(entry->username));
1081 if (!strchr(entry->username, '@')) {
1082 strncat(uh, "@", 1);
1083 strcat(uh, "*private*");
1086 if (entry->userinfo)
1088 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1090 2, idp->data, idp->len,
1094 strlen(entry->userinfo));
1097 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1099 2, idp->data, idp->len,
1103 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1104 0, packet->data, packet->len, FALSE);
1106 silc_buffer_free(packet);
1107 silc_buffer_free(idp);
1110 if (found == FALSE && entry)
1111 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1112 SILC_STATUS_ERR_NO_SUCH_NICK,
1114 strlen(entry->nickname));
1118 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1120 SilcServer server = cmd->server;
1121 char *nick = NULL, *server_name = NULL;
1122 int count = 0, clients_count = 0;
1123 SilcClientEntry *clients = NULL;
1126 /* Protocol dictates that we must always send the received WHOWAS request
1127 to our router if we are normal server, so let's do it now unless we
1128 are standalone. We will not send any replies to the client until we
1129 have received reply from the router. */
1130 if (server->server_type == SILC_SERVER &&
1131 !cmd->pending && !server->standalone) {
1133 unsigned short old_ident;
1135 old_ident = silc_command_get_ident(cmd->payload);
1136 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1137 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1139 /* Send WHOWAS command to our router */
1140 silc_server_packet_send(server, (SilcSocketConnection)
1141 server->router->connection,
1142 SILC_PACKET_COMMAND, cmd->packet->flags,
1143 tmpbuf->data, tmpbuf->len, TRUE);
1145 /* Reprocess this packet after received reply from router */
1146 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1147 silc_command_get_ident(cmd->payload),
1148 silc_server_command_destructor,
1149 silc_server_command_whowas,
1150 silc_server_command_dup(cmd));
1151 cmd->pending = TRUE;
1153 silc_command_set_ident(cmd->payload, old_ident);
1155 silc_buffer_free(tmpbuf);
1160 /* We are ready to process the command request. Let's search for the
1161 requested client and send reply to the requesting client. */
1163 /* Parse the whowas request */
1164 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1167 /* Get all clients matching that nickname from local list */
1168 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1172 clients = silc_idlist_get_clients_by_hash(server->local_list,
1173 nick, server->md5hash,
1176 /* Check global list as well */
1178 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1182 clients = silc_idlist_get_clients_by_hash(server->global_list,
1183 nick, server->md5hash,
1187 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1192 /* Send the command reply to the client */
1193 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1201 silc_free(server_name);
1207 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1209 SilcServer server = cmd->server;
1210 char *nick = NULL, *server_name = NULL;
1211 int count = 0, clients_count = 0;
1212 SilcClientEntry *clients = NULL;
1215 /* Parse the whowas request */
1216 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1219 /* Process the command request. Let's search for the requested client and
1220 send reply to the requesting server. */
1222 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1226 clients = silc_idlist_get_clients_by_hash(server->local_list,
1227 nick, server->md5hash,
1230 /* If we are router we will check our global list as well. */
1231 if (!clients && server->server_type == SILC_ROUTER) {
1232 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1236 clients = silc_idlist_get_clients_by_hash(server->global_list,
1237 nick, server->md5hash,
1242 /* Such a client really does not exist in the SILC network. */
1243 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1244 SILC_STATUS_ERR_NO_SUCH_NICK,
1245 3, nick, strlen(nick));
1249 /* Send the command reply to the client */
1250 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1258 silc_free(server_name);
1263 /* Server side of command WHOWAS. */
1265 SILC_SERVER_CMD_FUNC(whowas)
1267 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1270 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1272 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1273 ret = silc_server_command_whowas_from_client(cmd);
1274 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1275 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1276 ret = silc_server_command_whowas_from_server(cmd);
1279 silc_server_command_free(cmd);
1282 /******************************************************************************
1286 ******************************************************************************/
1288 /* Checks that all mandatory fields are present. If not then send WHOIS
1289 request to the server who owns the client. We use WHOIS because we want
1290 to get as much information as possible at once. */
1293 silc_server_command_identify_check(SilcServerCommandContext cmd,
1294 SilcClientEntry *clients,
1295 unsigned int clients_count)
1297 SilcServer server = cmd->server;
1299 SilcClientEntry entry;
1301 for (i = 0; i < clients_count; i++) {
1304 if (entry->data.registered == FALSE)
1307 if (!entry->nickname) {
1309 unsigned short old_ident;
1314 old_ident = silc_command_get_ident(cmd->payload);
1315 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1316 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1317 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1319 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1320 now anyway so make it a good one. */
1321 silc_server_packet_send(server, entry->router->connection,
1322 SILC_PACKET_COMMAND, cmd->packet->flags,
1323 tmpbuf->data, tmpbuf->len, TRUE);
1325 /* Reprocess this packet after received reply */
1326 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1327 silc_command_get_ident(cmd->payload),
1328 silc_server_command_destructor,
1329 silc_server_command_identify,
1330 silc_server_command_dup(cmd));
1332 cmd->pending = TRUE;
1334 /* Put old data back to the Command Payload we just changed */
1335 silc_command_set_ident(cmd->payload, old_ident);
1336 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1338 silc_buffer_free(tmpbuf);
1347 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1348 SilcClientEntry *clients,
1349 unsigned int clients_count,
1352 SilcServer server = cmd->server;
1355 SilcBuffer packet, idp;
1356 SilcClientEntry entry;
1357 SilcCommandStatus status;
1358 unsigned short ident = silc_command_get_ident(cmd->payload);
1359 char nh[256], uh[256];
1360 SilcSocketConnection hsock;
1363 for (i = 0; i < clients_count; i++)
1364 if (clients[i]->data.registered)
1367 status = SILC_STATUS_OK;
1369 status = SILC_STATUS_LIST_START;
1371 for (i = 0, k = 0; i < clients_count; i++) {
1374 if (entry->data.registered == FALSE) {
1375 if (clients_count == 1) {
1376 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1377 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1378 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1379 2, idp->data, idp->len);
1380 silc_buffer_free(idp);
1386 status = SILC_STATUS_LIST_ITEM;
1388 if (clients_count > 1 && k == clients_count - 1)
1389 status = SILC_STATUS_LIST_END;
1391 if (count && k - 1 == count)
1392 status = SILC_STATUS_LIST_END;
1394 if (count && k - 1 > count)
1397 /* Send IDENTIFY reply */
1398 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1399 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1401 memset(uh, 0, sizeof(uh));
1402 memset(nh, 0, sizeof(nh));
1404 strncat(nh, entry->nickname, strlen(entry->nickname));
1405 if (!strchr(entry->nickname, '@')) {
1406 strncat(nh, "@", 1);
1407 len = entry->router ? strlen(entry->router->server_name) :
1408 strlen(server->server_name);
1409 strncat(nh, entry->router ? entry->router->server_name :
1410 server->server_name, len);
1413 if (!entry->username) {
1414 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1416 2, idp->data, idp->len,
1419 strncat(uh, entry->username, strlen(entry->username));
1420 if (!strchr(entry->username, '@')) {
1421 strncat(uh, "@", 1);
1422 hsock = (SilcSocketConnection)entry->connection;
1423 len = strlen(hsock->hostname);
1424 strncat(uh, hsock->hostname, len);
1427 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1429 2, idp->data, idp->len,
1434 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1435 0, packet->data, packet->len, FALSE);
1437 silc_buffer_free(packet);
1438 silc_buffer_free(idp);
1445 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1447 SilcServer server = cmd->server;
1448 char *nick = NULL, *server_name = NULL;
1449 int count = 0, clients_count = 0;
1450 SilcClientEntry *clients = NULL, entry;
1451 SilcClientID **client_id = NULL;
1452 unsigned int client_id_count = 0;
1455 /* Protocol dictates that we must always send the received IDENTIFY request
1456 to our router if we are normal server, so let's do it now unless we
1457 are standalone. We will not send any replies to the client until we
1458 have received reply from the router. */
1459 if (server->server_type == SILC_SERVER &&
1460 !cmd->pending && !server->standalone) {
1462 unsigned short old_ident;
1464 old_ident = silc_command_get_ident(cmd->payload);
1465 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1466 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1468 /* Send IDENTIFY command to our router */
1469 silc_server_packet_send(server, (SilcSocketConnection)
1470 server->router->connection,
1471 SILC_PACKET_COMMAND, cmd->packet->flags,
1472 tmpbuf->data, tmpbuf->len, TRUE);
1474 /* Reprocess this packet after received reply from router */
1475 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1476 silc_command_get_ident(cmd->payload),
1477 silc_server_command_destructor,
1478 silc_server_command_identify,
1479 silc_server_command_dup(cmd));
1480 cmd->pending = TRUE;
1482 silc_command_set_ident(cmd->payload, old_ident);
1484 silc_buffer_free(tmpbuf);
1489 /* We are ready to process the command request. Let's search for the
1490 requested client and send reply to the requesting client. */
1492 /* Parse the IDENTIFY request */
1493 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1494 &nick, &server_name, &count,
1495 SILC_COMMAND_IDENTIFY))
1498 /* Get all clients matching that ID or nickname from local list */
1499 if (client_id_count) {
1500 /* Check all Client ID's received in the command packet */
1501 for (i = 0; i < client_id_count; i++) {
1502 entry = silc_idlist_find_client_by_id(server->local_list,
1503 client_id[i], NULL);
1505 clients = silc_realloc(clients, sizeof(*clients) *
1506 (clients_count + 1));
1507 clients[clients_count++] = entry;
1511 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1515 clients = silc_idlist_get_clients_by_hash(server->local_list,
1516 nick, server->md5hash,
1520 /* Check global list as well */
1522 if (client_id_count) {
1523 /* Check all Client ID's received in the command packet */
1524 for (i = 0; i < client_id_count; i++) {
1525 entry = silc_idlist_find_client_by_id(server->global_list,
1526 client_id[i], NULL);
1528 clients = silc_realloc(clients, sizeof(*clients) *
1529 (clients_count + 1));
1530 clients[clients_count++] = entry;
1534 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1538 clients = silc_idlist_get_clients_by_hash(server->global_list,
1539 nick, server->md5hash,
1545 /* Such a client really does not exist in the SILC network. */
1546 if (!client_id_count) {
1547 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1548 SILC_STATUS_ERR_NO_SUCH_NICK,
1549 3, nick, strlen(nick));
1551 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1552 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1553 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1554 2, idp->data, idp->len);
1555 silc_buffer_free(idp);
1560 /* Check that all mandatory fields are present and request those data
1561 from the server who owns the client if necessary. */
1562 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1567 /* Send the command reply to the client */
1568 silc_server_command_identify_send_reply(cmd, clients, clients_count,
1572 if (client_id_count) {
1573 for (i = 0; i < client_id_count; i++)
1574 silc_free(client_id[i]);
1575 silc_free(client_id);
1582 silc_free(server_name);
1588 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1590 SilcServer server = cmd->server;
1591 char *nick = NULL, *server_name = NULL;
1592 int count = 0, clients_count = 0;
1593 SilcClientEntry *clients = NULL, entry;
1594 SilcClientID **client_id = NULL;
1595 unsigned int client_id_count = 0;
1598 /* Parse the IDENTIFY request */
1599 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1600 &nick, &server_name, &count,
1601 SILC_COMMAND_IDENTIFY))
1604 /* Process the command request. Let's search for the requested client and
1605 send reply to the requesting server. */
1607 if (client_id_count) {
1608 /* Check all Client ID's received in the command packet */
1609 for (i = 0; i < client_id_count; i++) {
1610 entry = silc_idlist_find_client_by_id(server->local_list,
1611 client_id[i], NULL);
1613 clients = silc_realloc(clients, sizeof(*clients) *
1614 (clients_count + 1));
1615 clients[clients_count++] = entry;
1619 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1623 clients = silc_idlist_get_clients_by_hash(server->local_list,
1624 nick, server->md5hash,
1628 /* If we are router we will check our global list as well. */
1629 if (!clients && server->server_type == SILC_ROUTER) {
1630 if (client_id_count) {
1631 /* Check all Client ID's received in the command packet */
1632 for (i = 0; i < client_id_count; i++) {
1633 entry = silc_idlist_find_client_by_id(server->global_list,
1634 client_id[i], NULL);
1636 clients = silc_realloc(clients, sizeof(*clients) *
1637 (clients_count + 1));
1638 clients[clients_count++] = entry;
1642 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1646 clients = silc_idlist_get_clients_by_hash(server->global_list,
1647 nick, server->md5hash,
1653 /* Such a client really does not exist in the SILC network. */
1654 if (!client_id_count) {
1655 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1656 SILC_STATUS_ERR_NO_SUCH_NICK,
1657 3, nick, strlen(nick));
1659 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1660 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1661 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1662 2, idp->data, idp->len);
1663 silc_buffer_free(idp);
1668 /* Check that all mandatory fields are present and request those data
1669 from the server who owns the client if necessary. */
1670 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1675 /* Send the command reply */
1676 silc_server_command_identify_send_reply(cmd, clients, clients_count, count);
1679 if (client_id_count) {
1680 for (i = 0; i < client_id_count; i++)
1681 silc_free(client_id[i]);
1682 silc_free(client_id);
1689 silc_free(server_name);
1694 SILC_SERVER_CMD_FUNC(identify)
1696 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1699 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1701 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1702 ret = silc_server_command_identify_from_client(cmd);
1703 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1704 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1705 ret = silc_server_command_identify_from_server(cmd);
1708 silc_server_command_free(cmd);
1711 /* Checks string for bad characters and returns TRUE if they are found. */
1713 static int silc_server_command_bad_chars(char *nick)
1715 if (strchr(nick, '\\')) return TRUE;
1716 if (strchr(nick, '\"')) return TRUE;
1717 if (strchr(nick, '´')) return TRUE;
1718 if (strchr(nick, '`')) return TRUE;
1719 if (strchr(nick, '\'')) return TRUE;
1720 if (strchr(nick, '*')) return TRUE;
1721 if (strchr(nick, '/')) return TRUE;
1722 if (strchr(nick, '@')) return TRUE;
1727 /* Server side of command NICK. Sets nickname for user. Setting
1728 nickname causes generation of a new client ID for the client. The
1729 new client ID is sent to the client after changing the nickname. */
1731 SILC_SERVER_CMD_FUNC(nick)
1733 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1734 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1735 SilcServer server = cmd->server;
1736 SilcBuffer packet, nidp, oidp;
1737 SilcClientID *new_id;
1739 unsigned short ident = silc_command_get_ident(cmd->payload);
1741 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1744 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1746 /* Check nickname */
1747 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1748 if (silc_server_command_bad_chars(nick) == TRUE) {
1749 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1750 SILC_STATUS_ERR_BAD_NICKNAME);
1754 if (strlen(nick) > 128)
1757 /* Create new Client ID */
1758 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1759 cmd->server->md5hash, nick,
1762 /* Send notify about nickname change to our router. We send the new
1763 ID and ask to replace it with the old one. If we are router the
1764 packet is broadcasted. Send NICK_CHANGE notify. */
1765 if (!server->standalone)
1766 silc_server_send_notify_nick_change(server, server->router->connection,
1767 server->server_type == SILC_SERVER ?
1768 FALSE : TRUE, client->id,
1769 new_id, SILC_ID_CLIENT_LEN);
1771 /* Remove old cache entry */
1772 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1775 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1779 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1780 silc_free(client->id);
1783 /* Save the nickname as this client is our local client */
1784 if (client->nickname)
1785 silc_free(client->nickname);
1787 client->nickname = strdup(nick);
1788 client->id = new_id;
1790 /* Update client cache */
1791 silc_idcache_add(server->local_list->clients, client->nickname,
1792 strlen(client->nickname), SILC_ID_CLIENT, client->id,
1793 (void *)client, TRUE, FALSE);
1795 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1797 /* Send NICK_CHANGE notify to the client's channels */
1798 silc_server_send_notify_on_channels(server, NULL, client,
1799 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1800 oidp->data, oidp->len,
1801 nidp->data, nidp->len);
1803 /* Send the new Client ID as reply command back to client */
1804 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1805 SILC_STATUS_OK, ident, 1,
1806 2, nidp->data, nidp->len);
1807 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1808 0, packet->data, packet->len, FALSE);
1810 silc_buffer_free(packet);
1811 silc_buffer_free(nidp);
1812 silc_buffer_free(oidp);
1815 silc_server_command_free(cmd);
1818 /* Sends the LIST command reply */
1821 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1822 SilcChannelEntry *lch,
1823 unsigned int lch_count,
1824 SilcChannelEntry *gch,
1825 unsigned int gch_count)
1828 SilcBuffer packet, idp;
1829 SilcChannelEntry entry;
1830 SilcCommandStatus status;
1831 unsigned short ident = silc_command_get_ident(cmd->payload);
1833 unsigned char usercount[4];
1836 for (i = 0; i < lch_count; i++)
1837 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1839 for (i = 0; i < gch_count; i++)
1840 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1843 status = SILC_STATUS_OK;
1844 if ((lch_count + gch_count) > 1)
1845 status = SILC_STATUS_LIST_START;
1848 for (i = 0; i < lch_count; i++) {
1855 status = SILC_STATUS_LIST_ITEM;
1857 if (i == lch_count - 1 && gch_count)
1859 if (lch_count > 1 && i == lch_count - 1)
1860 status = SILC_STATUS_LIST_END;
1862 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1864 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1865 topic = "*private*";
1866 memset(usercount, 0, sizeof(usercount));
1868 topic = entry->topic;
1869 users = silc_list_count(entry->user_list);
1870 SILC_PUT32_MSB(users, usercount);
1873 /* Send the reply */
1876 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1878 2, idp->data, idp->len,
1879 3, entry->channel_name,
1880 strlen(entry->channel_name),
1881 4, topic, strlen(topic),
1885 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1887 2, idp->data, idp->len,
1888 3, entry->channel_name,
1889 strlen(entry->channel_name),
1891 silc_server_packet_send(cmd->server, cmd->sock,
1892 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1893 packet->len, FALSE);
1894 silc_buffer_free(packet);
1895 silc_buffer_free(idp);
1898 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1901 for (i = 0; i < gch_count; i++) {
1908 status = SILC_STATUS_LIST_ITEM;
1910 if (gch_count > 1 && i == lch_count - 1)
1911 status = SILC_STATUS_LIST_END;
1913 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1915 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1916 topic = "*private*";
1917 memset(usercount, 0, sizeof(usercount));
1919 topic = entry->topic;
1920 users = silc_list_count(entry->user_list);
1921 SILC_PUT32_MSB(users, usercount);
1924 /* Send the reply */
1927 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1929 2, idp->data, idp->len,
1930 3, entry->channel_name,
1931 strlen(entry->channel_name),
1932 4, topic, strlen(topic),
1936 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1938 2, idp->data, idp->len,
1939 3, entry->channel_name,
1940 strlen(entry->channel_name),
1942 silc_server_packet_send(cmd->server, cmd->sock,
1943 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1944 packet->len, FALSE);
1945 silc_buffer_free(packet);
1946 silc_buffer_free(idp);
1950 /* Server side of LIST command. This lists the channel of the requested
1951 server. Secret channels are not listed. */
1953 SILC_SERVER_CMD_FUNC(list)
1955 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1956 SilcServer server = cmd->server;
1957 SilcChannelID *channel_id = NULL;
1959 unsigned int tmp_len;
1960 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1961 unsigned int lch_count = 0, gch_count = 0;
1963 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1965 /* Get Channel ID */
1966 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1968 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1971 SILC_STATUS_ERR_NO_CHANNEL_ID);
1976 /* Get the channels from local list */
1977 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1980 /* Get the channels from global list if we are router */
1981 if (server->server_type == SILC_ROUTER)
1982 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1985 /* Send the reply */
1986 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
1987 gchannels, gch_count);
1990 silc_server_command_free(cmd);
1993 /* Server side of TOPIC command. Sets topic for channel and/or returns
1994 current topic to client. */
1996 SILC_SERVER_CMD_FUNC(topic)
1998 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1999 SilcServer server = cmd->server;
2000 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2001 SilcChannelID *channel_id;
2002 SilcChannelEntry channel;
2003 SilcChannelClientEntry chl;
2004 SilcBuffer packet, idp;
2006 unsigned int argc, tmp_len;
2007 unsigned short ident = silc_command_get_ident(cmd->payload);
2009 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
2011 argc = silc_argument_get_arg_num(cmd->args);
2013 /* Get Channel ID */
2014 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2016 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2017 SILC_STATUS_ERR_NO_CHANNEL_ID);
2020 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2022 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2023 SILC_STATUS_ERR_NO_CHANNEL_ID);
2027 /* Check whether the channel exists */
2028 channel = silc_idlist_find_channel_by_id(server->local_list,
2031 channel = silc_idlist_find_channel_by_id(server->global_list,
2034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2035 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2042 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2044 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2045 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2049 if (strlen(tmp) > 256) {
2050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2051 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2055 /* See whether has rights to change topic */
2056 silc_list_start(channel->user_list);
2057 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2058 if (chl->client == client)
2061 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2062 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2063 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2064 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2069 /* Set the topic for channel */
2071 silc_free(channel->topic);
2072 channel->topic = strdup(tmp);
2074 /* Send TOPIC_SET notify type to the network */
2075 if (!server->standalone)
2076 silc_server_send_notify_topic_set(server, server->router->connection,
2077 server->server_type == SILC_ROUTER ?
2078 TRUE : FALSE, channel, client->id,
2079 SILC_ID_CLIENT_LEN, channel->topic);
2081 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2083 /* Send notify about topic change to all clients on the channel */
2084 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2085 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2086 idp->data, idp->len,
2087 channel->topic, strlen(channel->topic));
2088 silc_buffer_free(idp);
2091 /* Send the topic to client as reply packet */
2092 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2094 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2095 SILC_STATUS_OK, ident, 2,
2096 2, idp->data, idp->len,
2098 strlen(channel->topic));
2100 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2101 SILC_STATUS_OK, ident, 1,
2102 2, idp->data, idp->len);
2103 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2104 0, packet->data, packet->len, FALSE);
2106 silc_buffer_free(packet);
2107 silc_buffer_free(idp);
2108 silc_free(channel_id);
2111 silc_server_command_free(cmd);
2114 /* Server side of INVITE command. Invites some client to join some channel.
2115 This command is also used to manage the invite list of the channel. */
2117 SILC_SERVER_CMD_FUNC(invite)
2119 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2120 SilcServer server = cmd->server;
2121 SilcSocketConnection sock = cmd->sock, dest_sock;
2122 SilcChannelClientEntry chl;
2123 SilcClientEntry sender, dest;
2124 SilcClientID *dest_id = NULL;
2125 SilcChannelEntry channel;
2126 SilcChannelID *channel_id = NULL;
2127 SilcIDListData idata;
2128 SilcBuffer idp, idp2, packet;
2129 unsigned char *tmp, *add, *del;
2131 unsigned short ident = silc_command_get_ident(cmd->payload);
2133 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2135 /* Get Channel ID */
2136 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2139 SILC_STATUS_ERR_NO_CHANNEL_ID);
2142 channel_id = silc_id_payload_parse_id(tmp, len);
2144 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2145 SILC_STATUS_ERR_NO_CHANNEL_ID);
2149 /* Get the channel entry */
2150 channel = silc_idlist_find_channel_by_id(server->local_list,
2153 channel = silc_idlist_find_channel_by_id(server->global_list,
2156 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2157 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2162 /* Check whether the sender of this command is on the channel. */
2163 sender = (SilcClientEntry)sock->user_data;
2164 if (!silc_server_client_on_channel(sender, channel)) {
2165 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2166 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2170 /* Check whether the channel is invite-only channel. If yes then the
2171 sender of this command must be at least channel operator. */
2172 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2173 silc_list_start(channel->user_list);
2174 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2175 if (chl->client == sender) {
2176 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2177 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2178 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2185 /* Get destination client ID */
2186 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2190 dest_id = silc_id_payload_parse_id(tmp, len);
2192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2193 SILC_STATUS_ERR_NO_CLIENT_ID);
2197 /* Get the client entry */
2198 dest = silc_server_get_client_resolve(server, dest_id);
2200 if (server->server_type == SILC_ROUTER) {
2201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2202 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2206 /* The client info is being resolved. Reprocess this packet after
2207 receiving the reply to the query. */
2208 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2210 silc_server_command_destructor,
2211 silc_server_command_invite,
2212 silc_server_command_dup(cmd));
2213 cmd->pending = TRUE;
2214 silc_free(channel_id);
2219 /* Check whether the requested client is already on the channel. */
2220 if (silc_server_client_on_channel(dest, channel)) {
2221 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2222 SILC_STATUS_ERR_USER_ON_CHANNEL);
2226 /* Get route to the client */
2227 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2229 memset(invite, 0, sizeof(invite));
2230 strncat(invite, dest->nickname, strlen(dest->nickname));
2231 strncat(invite, "!", 1);
2232 strncat(invite, dest->username, strlen(dest->username));
2233 if (!strchr(dest->username, '@')) {
2234 strncat(invite, "@", 1);
2235 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2238 len = strlen(invite);
2239 if (!channel->invite_list)
2240 channel->invite_list = silc_calloc(len + 2,
2241 sizeof(*channel->invite_list));
2243 channel->invite_list = silc_realloc(channel->invite_list,
2244 sizeof(*channel->invite_list) *
2246 strlen(channel->invite_list) + 2));
2247 strncat(channel->invite_list, invite, len);
2248 strncat(channel->invite_list, ",", 1);
2250 /* Send notify to the client that is invited to the channel */
2251 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2252 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2253 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2255 SILC_NOTIFY_TYPE_INVITE, 3,
2256 idp->data, idp->len,
2257 channel->channel_name,
2258 strlen(channel->channel_name),
2259 idp2->data, idp2->len);
2260 silc_buffer_free(idp);
2261 silc_buffer_free(idp2);
2264 /* Add the client to the invite list of the channel */
2265 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2267 if (!channel->invite_list)
2268 channel->invite_list = silc_calloc(len + 2,
2269 sizeof(*channel->invite_list));
2271 channel->invite_list = silc_realloc(channel->invite_list,
2272 sizeof(*channel->invite_list) *
2274 strlen(channel->invite_list) + 2));
2275 if (add[len - 1] == ',')
2276 add[len - 1] = '\0';
2278 strncat(channel->invite_list, add, len);
2279 strncat(channel->invite_list, ",", 1);
2282 /* Get the invite to be removed and remove it from the list */
2283 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2284 if (del && channel->invite_list) {
2285 char *start, *end, *n;
2287 if (!strncmp(channel->invite_list, del,
2288 strlen(channel->invite_list) - 1)) {
2289 silc_free(channel->invite_list);
2290 channel->invite_list = NULL;
2292 start = strstr(channel->invite_list, del);
2293 if (start && strlen(start) >= len) {
2295 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2296 strncat(n, channel->invite_list, start - channel->invite_list);
2297 strncat(n, end + 1, ((channel->invite_list +
2298 strlen(channel->invite_list)) - end) - 1);
2299 silc_free(channel->invite_list);
2300 channel->invite_list = n;
2305 /* Send notify to the primary router */
2306 if (!server->standalone)
2307 silc_server_send_notify_invite(server, server->router->connection,
2308 server->server_type == SILC_ROUTER ?
2309 TRUE : FALSE, channel,
2310 sender->id, SILC_ID_CLIENT_LEN,
2313 /* Send command reply */
2314 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2315 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2316 SILC_STATUS_OK, ident, 2,
2318 3, channel->invite_list,
2319 channel->invite_list ?
2320 strlen(channel->invite_list) :
2322 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2323 packet->data, packet->len, FALSE);
2324 silc_buffer_free(packet);
2330 silc_free(channel_id);
2331 silc_server_command_free(cmd);
2336 SilcSocketConnection sock;
2340 /* Quits connection to client. This gets called if client won't
2341 close the connection even when it has issued QUIT command. */
2343 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2345 QuitInternal q = (QuitInternal)context;
2347 /* Free all client specific data, such as client entry and entires
2348 on channels this client may be on. */
2349 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2351 q->sock->user_data = NULL;
2353 /* Close the connection on our side */
2354 silc_server_close_connection(q->server, q->sock);
2356 silc_free(q->signoff);
2360 /* Quits SILC session. This is the normal way to disconnect client. */
2362 SILC_SERVER_CMD_FUNC(quit)
2364 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2365 SilcServer server = cmd->server;
2366 SilcSocketConnection sock = cmd->sock;
2368 unsigned char *tmp = NULL;
2369 unsigned int len = 0;
2371 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2373 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2376 /* Get destination ID */
2377 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2381 q = silc_calloc(1, sizeof(*q));
2384 q->signoff = tmp ? strdup(tmp) : NULL;
2386 /* We quit the connection with little timeout */
2387 silc_task_register(server->timeout_queue, sock->sock,
2388 silc_server_command_quit_cb, (void *)q,
2389 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2392 silc_server_command_free(cmd);
2395 /* Server side of command KILL. This command is used by router operator
2396 to remove an client from the SILC Network temporarily. */
2398 SILC_SERVER_CMD_FUNC(kill)
2400 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2401 SilcServer server = cmd->server;
2402 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2403 SilcClientEntry remote_client;
2404 SilcClientID *client_id;
2405 unsigned char *tmp, *comment;
2406 unsigned int tmp_len, tmp_len2;
2408 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2410 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2413 /* KILL command works only on router */
2414 if (server->server_type != SILC_ROUTER) {
2415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2416 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2420 /* Check whether client has the permissions. */
2421 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2423 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2427 /* Get the client ID */
2428 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2431 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2434 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2437 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2441 /* Get the client entry */
2442 remote_client = silc_idlist_find_client_by_id(server->local_list,
2444 if (!remote_client) {
2445 remote_client = silc_idlist_find_client_by_id(server->global_list,
2447 if (!remote_client) {
2448 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2449 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2455 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2459 /* Send reply to the sender */
2460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2463 /* Send the KILL notify packets. First send it to the channel, then
2464 to our primary router and then directly to the client who is being
2465 killed right now. */
2467 /* Send KILLED notify to the channels. It is not sent to the client
2468 as it will be sent differently destined directly to the client and not
2470 silc_server_send_notify_on_channels(server, remote_client,
2471 remote_client, SILC_NOTIFY_TYPE_KILLED,
2474 comment, comment ? tmp_len2 : 0);
2476 /* Send KILLED notify to primary route */
2477 if (!server->standalone)
2478 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2479 remote_client->id, SILC_ID_CLIENT_LEN,
2482 /* Send KILLED notify to the client directly */
2483 silc_server_send_notify_killed(server, remote_client->connection ?
2484 remote_client->connection :
2485 remote_client->router->connection, FALSE,
2486 remote_client->id, SILC_ID_CLIENT_LEN,
2489 /* Remove the client from all channels. This generates new keys to the
2490 channels as well. */
2491 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2494 /* Remove the client entry, If it is locally connected then we will also
2495 disconnect the client here */
2496 if (remote_client->data.registered && remote_client->connection) {
2497 /* Remove locally conneted client */
2498 SilcSocketConnection sock = remote_client->connection;
2499 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2500 silc_server_close_connection(server, sock);
2502 /* Remove remote client */
2503 if (!silc_idlist_del_client(server->global_list, remote_client))
2504 silc_idlist_del_client(server->local_list, remote_client);
2508 silc_server_command_free(cmd);
2511 /* Server side of command INFO. This sends information about us to
2512 the client. If client requested specific server we will send the
2513 command to that server. */
2515 SILC_SERVER_CMD_FUNC(info)
2517 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2518 SilcServer server = cmd->server;
2519 SilcBuffer packet, idp;
2521 unsigned int tmp_len;
2522 char *dest_server, *server_info = NULL, *server_name;
2523 unsigned short ident = silc_command_get_ident(cmd->payload);
2524 SilcServerEntry entry = NULL;
2525 SilcServerID *server_id = NULL;
2527 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 0, 2);
2529 /* Get server name */
2530 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2533 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2535 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2537 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2538 SILC_STATUS_ERR_NO_SERVER_ID);
2544 /* Check whether we have this server cached */
2545 entry = silc_idlist_find_server_by_id(server->local_list,
2548 entry = silc_idlist_find_server_by_id(server->global_list,
2550 if (!entry && server->server_type == SILC_ROUTER) {
2551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2552 SILC_STATUS_ERR_NO_SUCH_SERVER);
2558 if ((!dest_server && !server_id) ||
2559 (dest_server && !cmd->pending &&
2560 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2561 /* Send our reply */
2562 char info_string[256];
2564 memset(info_string, 0, sizeof(info_string));
2565 snprintf(info_string, sizeof(info_string),
2566 "location: %s server: %s admin: %s <%s>",
2567 server->config->admin_info->location,
2568 server->config->admin_info->server_type,
2569 server->config->admin_info->admin_name,
2570 server->config->admin_info->admin_email);
2572 server_info = info_string;
2573 entry = server->id_entry;
2575 /* Check whether we have this server cached */
2576 if (!entry && dest_server) {
2577 entry = silc_idlist_find_server_by_name(server->global_list,
2580 entry = silc_idlist_find_server_by_name(server->local_list,
2585 if (!cmd->pending &&
2586 server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2587 /* Send to the server */
2589 unsigned short old_ident;
2591 old_ident = silc_command_get_ident(cmd->payload);
2592 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2593 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2595 silc_server_packet_send(server, entry->connection,
2596 SILC_PACKET_COMMAND, cmd->packet->flags,
2597 tmpbuf->data, tmpbuf->len, TRUE);
2599 /* Reprocess this packet after received reply from router */
2600 silc_server_command_pending(server, SILC_COMMAND_INFO,
2601 silc_command_get_ident(cmd->payload),
2602 silc_server_command_destructor,
2603 silc_server_command_info,
2604 silc_server_command_dup(cmd));
2605 cmd->pending = TRUE;
2606 silc_command_set_ident(cmd->payload, old_ident);
2607 silc_buffer_free(tmpbuf);
2611 if (!entry && !cmd->pending && !server->standalone) {
2612 /* Send to the primary router */
2614 unsigned short old_ident;
2616 old_ident = silc_command_get_ident(cmd->payload);
2617 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2618 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2620 silc_server_packet_send(server, server->router->connection,
2621 SILC_PACKET_COMMAND, cmd->packet->flags,
2622 tmpbuf->data, tmpbuf->len, TRUE);
2624 /* Reprocess this packet after received reply from router */
2625 silc_server_command_pending(server, SILC_COMMAND_INFO,
2626 silc_command_get_ident(cmd->payload),
2627 silc_server_command_destructor,
2628 silc_server_command_info,
2629 silc_server_command_dup(cmd));
2630 cmd->pending = TRUE;
2631 silc_command_set_ident(cmd->payload, old_ident);
2632 silc_buffer_free(tmpbuf);
2638 silc_free(server_id);
2641 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2642 SILC_STATUS_ERR_NO_SUCH_SERVER);
2646 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2648 server_info = entry->server_info;
2649 server_name = entry->server_name;
2651 /* Send the reply */
2652 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2653 SILC_STATUS_OK, ident, 3,
2654 2, idp->data, idp->len,
2656 strlen(server_name),
2658 strlen(server_info));
2659 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2660 packet->data, packet->len, FALSE);
2662 silc_buffer_free(packet);
2663 silc_buffer_free(idp);
2666 silc_server_command_free(cmd);
2669 /* Server side of command PING. This just replies to the ping. */
2671 SILC_SERVER_CMD_FUNC(ping)
2673 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2674 SilcServer server = cmd->server;
2679 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2682 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2685 SILC_STATUS_ERR_NO_SERVER_ID);
2688 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2692 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2693 /* Send our reply */
2694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2697 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2698 SILC_STATUS_ERR_NO_SUCH_SERVER);
2705 silc_server_command_free(cmd);
2708 /* Internal routine to join channel. The channel sent to this function
2709 has been either created or resolved from ID lists. This joins the sent
2710 client to the channel. */
2712 static void silc_server_command_join_channel(SilcServer server,
2713 SilcServerCommandContext cmd,
2714 SilcChannelEntry channel,
2715 SilcClientID *client_id,
2719 SilcSocketConnection sock = cmd->sock;
2721 unsigned int tmp_len, user_count;
2722 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2723 SilcClientEntry client;
2724 SilcChannelClientEntry chl;
2725 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2726 unsigned short ident = silc_command_get_ident(cmd->payload);
2729 SILC_LOG_DEBUG(("Start"));
2734 /* Get the client entry */
2735 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2736 client = (SilcClientEntry)sock->user_data;
2738 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2745 * Check channel modes
2748 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2749 strncat(check, client->nickname, strlen(client->nickname));
2750 if (!strchr(client->nickname, '@')) {
2751 strncat(check, "@", 1);
2752 strncat(check, server->server_name, strlen(server->server_name));
2754 strncat(check, "!", 1);
2755 strncat(check, client->username, strlen(client->username));
2756 if (!strchr(client->username, '@')) {
2757 strncat(check, "@", 1);
2758 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2762 /* Check invite list if channel is invite-only channel */
2763 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
2764 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2765 if (!channel->invite_list) {
2766 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2767 SILC_STATUS_ERR_NOT_INVITED);
2771 if (!silc_string_match(channel->invite_list, check)) {
2772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2773 SILC_STATUS_ERR_NOT_INVITED);
2778 /* Check ban list if it exists. If the client's nickname, server,
2779 username and/or hostname is in the ban list the access to the
2780 channel is denied. */
2781 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2782 if (silc_string_match(channel->ban_list, check)) {
2783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2784 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2789 /* Get passphrase */
2790 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2792 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2793 memcpy(passphrase, tmp, tmp_len);
2796 /* Check the channel passphrase if set. */
2797 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2798 if (!passphrase || memcmp(channel->passphrase, passphrase,
2799 strlen(channel->passphrase))) {
2800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2801 SILC_STATUS_ERR_BAD_PASSWORD);
2806 /* Check user count limit if set. */
2807 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2808 if (silc_list_count(channel->user_list) + 1 >
2809 channel->user_limit) {
2810 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2811 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2817 * Client is allowed to join to the channel. Make it happen.
2820 /* Check whether the client already is on the channel */
2821 if (silc_server_client_on_channel(client, channel)) {
2822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2823 SILC_STATUS_ERR_USER_ON_CHANNEL);
2827 /* Generate new channel key as protocol dictates */
2828 if ((!created && silc_list_count(channel->user_list) > 0) ||
2829 !channel->channel_key)
2830 silc_server_create_channel_key(server, channel, 0);
2832 /* Send the channel key. This is broadcasted to the channel but is not
2833 sent to the client who is joining to the channel. */
2834 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2835 silc_server_send_channel_key(server, NULL, channel,
2836 server->server_type == SILC_ROUTER ?
2837 FALSE : !server->standalone);
2839 /* Join the client to the channel by adding it to channel's user list.
2840 Add also the channel to client entry's channels list for fast cross-
2842 chl = silc_calloc(1, sizeof(*chl));
2844 chl->client = client;
2845 chl->channel = channel;
2846 silc_list_add(channel->user_list, chl);
2847 silc_list_add(client->channels, chl);
2849 /* Get users on the channel */
2850 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2853 /* Encode Client ID Payload of the original client who wants to join */
2854 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2856 /* Encode command reply packet */
2857 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2858 SILC_PUT32_MSB(channel->mode, mode);
2859 SILC_PUT32_MSB(created, tmp2);
2860 SILC_PUT32_MSB(user_count, tmp3);
2862 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2863 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2864 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2865 strlen(channel->channel_key->
2867 channel->channel_key->cipher->name,
2868 channel->key_len / 8, channel->key);
2873 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2874 SILC_STATUS_OK, ident, 13,
2875 2, channel->channel_name,
2876 strlen(channel->channel_name),
2877 3, chidp->data, chidp->len,
2878 4, clidp->data, clidp->len,
2881 7, keyp ? keyp->data : NULL,
2882 keyp ? keyp->len : 0,
2883 8, channel->ban_list,
2885 strlen(channel->ban_list) : 0,
2886 9, channel->invite_list,
2887 channel->invite_list ?
2888 strlen(channel->invite_list) : 0,
2891 strlen(channel->topic) : 0,
2892 11, channel->hmac->hmac->name,
2893 strlen(channel->hmac->hmac->name),
2895 13, user_list->data, user_list->len,
2896 14, mode_list->data,
2899 /* Send command reply */
2900 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2901 reply->data, reply->len, FALSE);
2903 if (!cmd->pending) {
2904 /* Send JOIN notify to locally connected clients on the channel */
2905 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2906 SILC_NOTIFY_TYPE_JOIN, 2,
2907 clidp->data, clidp->len,
2908 chidp->data, chidp->len);
2910 /* Send JOIN notify packet to our primary router */
2911 if (!server->standalone)
2912 silc_server_send_notify_join(server, server->router->connection,
2913 server->server_type == SILC_ROUTER ?
2914 TRUE : FALSE, channel, client->id,
2915 SILC_ID_CLIENT_LEN);
2918 silc_buffer_free(reply);
2919 silc_buffer_free(clidp);
2920 silc_buffer_free(chidp);
2921 silc_buffer_free(keyp);
2922 silc_buffer_free(user_list);
2923 silc_buffer_free(mode_list);
2927 silc_free(passphrase);
2930 /* Server side of command JOIN. Joins client into requested channel. If
2931 the channel does not exist it will be created. */
2933 SILC_SERVER_CMD_FUNC(join)
2935 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2936 SilcServer server = cmd->server;
2938 char *tmp, *channel_name = NULL, *cipher, *hmac;
2939 SilcChannelEntry channel;
2940 unsigned int umode = 0;
2941 int created = FALSE;
2942 SilcClientID *client_id;
2944 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2946 /* Get channel name */
2947 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2950 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2955 if (strlen(channel_name) > 256)
2956 channel_name[255] = '\0';
2958 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2959 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2960 SILC_STATUS_ERR_BAD_CHANNEL);
2961 silc_free(channel_name);
2965 /* Get Client ID of the client who is joining to the channel */
2966 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2968 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2969 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2972 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2975 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2979 /* Get cipher and hmac name */
2980 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2981 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2983 /* See if the channel exists */
2984 channel = silc_idlist_find_channel_by_name(server->local_list,
2985 channel_name, NULL);
2987 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2988 /* If this is coming from client the Client ID in the command packet must
2989 be same as the client's ID. */
2990 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2991 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2992 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2993 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2994 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3000 /* Channel not found */
3002 /* If we are standalone server we don't have a router, we just create
3003 the channel by ourselves. */
3004 if (server->standalone) {
3005 channel = silc_server_create_new_channel(server, server->id, cipher,
3006 hmac, channel_name, TRUE);
3008 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3009 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3013 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3018 /* The channel does not exist on our server. If we are normal server
3019 we will send JOIN command to our router which will handle the
3020 joining procedure (either creates the channel if it doesn't exist
3021 or joins the client to it). */
3022 if (server->server_type == SILC_SERVER) {
3024 unsigned short old_ident;
3026 old_ident = silc_command_get_ident(cmd->payload);
3027 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3028 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3030 /* Send JOIN command to our router */
3031 silc_server_packet_send(server, (SilcSocketConnection)
3032 server->router->connection,
3033 SILC_PACKET_COMMAND, cmd->packet->flags,
3034 tmpbuf->data, tmpbuf->len, TRUE);
3036 /* Reprocess this packet after received reply from router */
3037 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3038 silc_command_get_ident(cmd->payload),
3039 silc_server_command_destructor,
3040 silc_server_command_join,
3041 silc_server_command_dup(cmd));
3042 cmd->pending = TRUE;
3046 /* We are router and the channel does not seem exist so we will check
3047 our global list as well for the channel. */
3048 channel = silc_idlist_find_channel_by_name(server->global_list,
3049 channel_name, NULL);
3051 /* Channel really does not exist, create it */
3052 channel = silc_server_create_new_channel(server, server->id, cipher,
3053 hmac, channel_name, TRUE);
3055 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3056 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3060 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3067 /* Channel not found */
3069 /* If the command came from router and/or we are normal server then
3070 something went wrong with the joining as the channel was not found.
3071 We can't do anything else but ignore this. */
3072 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3073 server->server_type == SILC_SERVER)
3076 /* We are router and the channel does not seem exist so we will check
3077 our global list as well for the channel. */
3078 channel = silc_idlist_find_channel_by_name(server->global_list,
3079 channel_name, NULL);
3081 /* Channel really does not exist, create it */
3082 channel = silc_server_create_new_channel(server, server->id, cipher,
3083 hmac, channel_name, TRUE);
3085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3086 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3090 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3096 /* If the channel does not have global users and is also empty it means the
3097 channel was created globally (by our router) and the client will be the
3098 channel founder and operator. */
3099 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3100 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3101 created = TRUE; /* Created globally by our router */
3104 /* Join to the channel */
3105 silc_server_command_join_channel(server, cmd, channel, client_id,
3108 silc_free(client_id);
3111 silc_server_command_free(cmd);
3114 /* Server side of command MOTD. Sends server's current "message of the
3115 day" to the client. */
3117 SILC_SERVER_CMD_FUNC(motd)
3119 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3120 SilcServer server = cmd->server;
3121 SilcBuffer packet, idp;
3122 char *motd, *dest_server;
3124 unsigned short ident = silc_command_get_ident(cmd->payload);
3126 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3128 /* Get server name */
3129 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3131 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3132 SILC_STATUS_ERR_NO_SUCH_SERVER);
3136 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3139 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3141 if (server->config && server->config->motd &&
3142 server->config->motd->motd_file) {
3144 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3149 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3150 SILC_STATUS_OK, ident, 2,
3156 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3157 SILC_STATUS_OK, ident, 1,
3161 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3162 packet->data, packet->len, FALSE);
3163 silc_buffer_free(packet);
3164 silc_buffer_free(idp);
3166 SilcServerEntry entry;
3168 /* Check whether we have this server cached */
3169 entry = silc_idlist_find_server_by_name(server->global_list,
3172 entry = silc_idlist_find_server_by_name(server->local_list,
3176 if (server->server_type == SILC_ROUTER && !cmd->pending &&
3177 entry && !entry->motd) {
3178 /* Send to the server */
3180 unsigned short old_ident;
3182 old_ident = silc_command_get_ident(cmd->payload);
3183 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3184 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3186 silc_server_packet_send(server, entry->connection,
3187 SILC_PACKET_COMMAND, cmd->packet->flags,
3188 tmpbuf->data, tmpbuf->len, TRUE);
3190 /* Reprocess this packet after received reply from router */
3191 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3192 silc_command_get_ident(cmd->payload),
3193 silc_server_command_destructor,
3194 silc_server_command_motd,
3195 silc_server_command_dup(cmd));
3196 cmd->pending = TRUE;
3197 silc_command_set_ident(cmd->payload, old_ident);
3198 silc_buffer_free(tmpbuf);
3202 if (!entry && !cmd->pending && !server->standalone) {
3203 /* Send to the primary router */
3205 unsigned short old_ident;
3207 old_ident = silc_command_get_ident(cmd->payload);
3208 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3209 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3211 silc_server_packet_send(server, server->router->connection,
3212 SILC_PACKET_COMMAND, cmd->packet->flags,
3213 tmpbuf->data, tmpbuf->len, TRUE);
3215 /* Reprocess this packet after received reply from router */
3216 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3217 silc_command_get_ident(cmd->payload),
3218 silc_server_command_destructor,
3219 silc_server_command_motd,
3220 silc_server_command_dup(cmd));
3221 cmd->pending = TRUE;
3222 silc_command_set_ident(cmd->payload, old_ident);
3223 silc_buffer_free(tmpbuf);
3228 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3229 SILC_STATUS_ERR_NO_SUCH_SERVER);
3233 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3236 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3237 SILC_STATUS_OK, ident, 2,
3240 strlen(entry->motd));
3242 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3243 SILC_STATUS_OK, ident, 1,
3246 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3247 packet->data, packet->len, FALSE);
3248 silc_buffer_free(packet);
3249 silc_buffer_free(idp);
3253 silc_server_command_free(cmd);
3256 /* Server side of command UMODE. Client can use this command to set/unset
3257 user mode. Client actually cannot set itself to be as server/router
3258 operator so this can be used only to unset the modes. */
3260 SILC_SERVER_CMD_FUNC(umode)
3262 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3263 SilcServer server = cmd->server;
3264 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3266 unsigned char *tmp_mask;
3268 unsigned short ident = silc_command_get_ident(cmd->payload);
3270 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3273 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3275 /* Get the client's mode mask */
3276 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3279 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3282 SILC_GET32_MSB(mask, tmp_mask);
3288 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3289 /* Cannot operator mode */
3290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3291 SILC_STATUS_ERR_PERM_DENIED);
3294 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3295 /* Remove the server operator rights */
3296 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3299 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3300 /* Cannot operator mode */
3301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3302 SILC_STATUS_ERR_PERM_DENIED);
3305 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3306 /* Remove the router operator rights */
3307 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3310 /* Send UMODE change to primary router */
3311 if (!server->standalone)
3312 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3313 client->id, SILC_ID_CLIENT_LEN,
3316 /* Send command reply to sender */
3317 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3318 SILC_STATUS_OK, ident, 1,
3320 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3321 packet->data, packet->len, FALSE);
3322 silc_buffer_free(packet);
3325 silc_server_command_free(cmd);
3328 /* Checks that client has rights to add or remove channel modes. If any
3329 of the checks fails FALSE is returned. */
3331 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3332 SilcChannelClientEntry client,
3335 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3336 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3338 /* Check whether has rights to change anything */
3339 if (!is_op && !is_fo)
3342 /* Check whether has rights to change everything */
3346 /* We know that client is channel operator, check that they are not
3347 changing anything that requires channel founder rights. Rest of the
3348 modes are available automatically for channel operator. */
3350 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3351 if (is_op && !is_fo)
3354 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3355 if (is_op && !is_fo)
3360 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3361 if (is_op && !is_fo)
3364 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3365 if (is_op && !is_fo)
3370 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3371 if (is_op && !is_fo)
3374 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3375 if (is_op && !is_fo)
3383 /* Server side command of CMODE. Changes channel mode */
3385 SILC_SERVER_CMD_FUNC(cmode)
3387 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3388 SilcServer server = cmd->server;
3389 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3390 SilcChannelID *channel_id;
3391 SilcChannelEntry channel;
3392 SilcChannelClientEntry chl;
3393 SilcBuffer packet, cidp;
3394 unsigned char *tmp, *tmp_id, *tmp_mask;
3395 char *cipher = NULL, *hmac = NULL;
3396 unsigned int argc, mode_mask, tmp_len, tmp_len2;
3397 unsigned short ident = silc_command_get_ident(cmd->payload);
3399 SILC_LOG_DEBUG(("Start"));
3401 argc = silc_argument_get_arg_num(cmd->args);
3403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3404 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3409 SILC_STATUS_ERR_TOO_MANY_PARAMS);
3413 /* Get Channel ID */
3414 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3416 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3417 SILC_STATUS_ERR_NO_CHANNEL_ID);
3420 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3423 SILC_STATUS_ERR_NO_CHANNEL_ID);
3427 /* Get the channel mode mask */
3428 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3431 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3434 SILC_GET32_MSB(mode_mask, tmp_mask);
3436 /* Get channel entry */
3437 channel = silc_idlist_find_channel_by_id(server->local_list,
3440 channel = silc_idlist_find_channel_by_id(server->global_list,
3443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3444 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3449 /* Check whether this client is on the channel */
3450 if (!silc_server_client_on_channel(client, channel)) {
3451 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3452 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3456 /* Get entry to the channel user list */
3457 silc_list_start(channel->user_list);
3458 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3459 if (chl->client == client)
3462 /* Check that client has rights to change any requested channel modes */
3463 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3464 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3465 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3470 * Check the modes. Modes that requires nothing special operation are
3474 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3475 /* Channel uses private keys to protect traffic. Client(s) has set the
3476 key locally they want to use, server does not know that key. */
3477 /* Nothing interesting to do here */
3479 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3480 /* The mode is removed and we need to generate and distribute
3481 new channel key. Clients are not using private channel keys
3482 anymore after this. */
3484 /* Re-generate channel key */
3485 silc_server_create_channel_key(server, channel, 0);
3487 /* Send the channel key. This sends it to our local clients and if
3488 we are normal server to our router as well. */
3489 silc_server_send_channel_key(server, NULL, channel,
3490 server->server_type == SILC_ROUTER ?
3491 FALSE : !server->standalone);
3493 cipher = channel->channel_key->cipher->name;
3494 hmac = channel->hmac->hmac->name;
3498 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3499 /* User limit is set on channel */
3500 unsigned int user_limit;
3502 /* Get user limit */
3503 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3505 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3506 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3507 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3511 SILC_GET32_MSB(user_limit, tmp);
3512 channel->user_limit = user_limit;
3515 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3516 /* User limit mode is unset. Remove user limit */
3517 channel->user_limit = 0;
3520 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3521 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3522 /* Passphrase has been set to channel */
3524 /* Get the passphrase */
3525 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3528 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3532 /* Save the passphrase */
3533 channel->passphrase = strdup(tmp);
3536 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3537 /* Passphrase mode is unset. remove the passphrase */
3538 if (channel->passphrase) {
3539 silc_free(channel->passphrase);
3540 channel->passphrase = NULL;
3545 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3546 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3547 /* Cipher to use protect the traffic */
3550 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3552 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3553 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3557 /* Delete old cipher and allocate the new one */
3558 silc_cipher_free(channel->channel_key);
3559 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3561 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3565 /* Re-generate channel key */
3566 silc_server_create_channel_key(server, channel, 0);
3568 /* Send the channel key. This sends it to our local clients and if
3569 we are normal server to our router as well. */
3570 silc_server_send_channel_key(server, NULL, channel,
3571 server->server_type == SILC_ROUTER ?
3572 FALSE : !server->standalone);
3575 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3576 /* Cipher mode is unset. Remove the cipher and revert back to
3578 cipher = channel->cipher;
3580 /* Delete old cipher and allocate default one */
3581 silc_cipher_free(channel->channel_key);
3582 if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc",
3583 &channel->channel_key)) {
3584 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3585 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3589 /* Re-generate channel key */
3590 silc_server_create_channel_key(server, channel, 0);
3592 /* Send the channel key. This sends it to our local clients and if
3593 we are normal server to our router as well. */
3594 silc_server_send_channel_key(server, NULL, channel,
3595 server->server_type == SILC_ROUTER ?
3596 FALSE : !server->standalone);
3600 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3601 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3602 /* HMAC to use protect the traffic */
3603 unsigned char hash[32];
3606 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3608 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3609 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3613 /* Delete old hmac and allocate the new one */
3614 silc_hmac_free(channel->hmac);
3615 if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3616 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3617 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3621 /* Set the HMAC key out of current channel key. The client must do
3623 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3625 silc_hmac_set_key(channel->hmac, hash,
3626 silc_hash_len(channel->hmac->hash));
3627 memset(hash, 0, sizeof(hash));
3630 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3631 /* Hmac mode is unset. Remove the hmac and revert back to
3633 unsigned char hash[32];
3634 hmac = channel->hmac_name;
3636 /* Delete old hmac and allocate default one */
3637 silc_hmac_free(channel->hmac);
3638 if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL,
3640 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3641 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3645 /* Set the HMAC key out of current channel key. The client must do
3647 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3649 silc_hmac_set_key(channel->hmac, hash,
3650 silc_hash_len(channel->hmac->hash));
3651 memset(hash, 0, sizeof(hash));
3655 /* Finally, set the mode */
3656 channel->mode = mode_mask;
3658 /* Send CMODE_CHANGE notify */
3659 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3660 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3661 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3662 cidp->data, cidp->len,
3664 cipher, cipher ? strlen(cipher) : 0,
3665 hmac, hmac ? strlen(hmac) : 0);
3667 /* Set CMODE notify type to network */
3668 if (!server->standalone)
3669 silc_server_send_notify_cmode(server, server->router->connection,
3670 server->server_type == SILC_ROUTER ?
3671 TRUE : FALSE, channel,
3672 mode_mask, client->id, SILC_ID_CLIENT,
3676 /* Send command reply to sender */
3677 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3678 SILC_STATUS_OK, ident, 1,
3680 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3681 packet->data, packet->len, FALSE);
3683 silc_buffer_free(packet);
3684 silc_free(channel_id);
3688 silc_server_command_free(cmd);
3691 /* Server side of CUMODE command. Changes client's mode on a channel. */
3693 SILC_SERVER_CMD_FUNC(cumode)
3695 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3696 SilcServer server = cmd->server;
3697 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3698 SilcChannelID *channel_id;
3699 SilcClientID *client_id;
3700 SilcChannelEntry channel;
3701 SilcClientEntry target_client;
3702 SilcChannelClientEntry chl;
3703 SilcBuffer packet, idp;
3704 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3705 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3707 unsigned short ident = silc_command_get_ident(cmd->payload);
3709 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3711 /* Get Channel ID */
3712 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3714 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3715 SILC_STATUS_ERR_NO_CHANNEL_ID);
3718 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3721 SILC_STATUS_ERR_NO_CHANNEL_ID);
3725 /* Get channel entry */
3726 channel = silc_idlist_find_channel_by_id(server->local_list,
3729 channel = silc_idlist_find_channel_by_id(server->global_list,
3732 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3733 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3738 /* Check whether sender is on the channel */
3739 if (!silc_server_client_on_channel(client, channel)) {
3740 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3741 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3745 /* Check that client has rights to change other's rights */
3746 silc_list_start(channel->user_list);
3747 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3748 if (chl->client == client) {
3749 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3750 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3751 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3752 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3756 sender_mask = chl->mode;
3761 /* Get the target client's channel mode mask */
3762 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3764 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3765 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3768 SILC_GET32_MSB(target_mask, tmp_mask);
3770 /* Get target Client ID */
3771 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3773 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3774 SILC_STATUS_ERR_NO_CLIENT_ID);
3777 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3779 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3780 SILC_STATUS_ERR_NO_CLIENT_ID);
3784 /* Get target client's entry */
3785 target_client = silc_idlist_find_client_by_id(server->local_list,
3787 if (!target_client) {
3788 target_client = silc_idlist_find_client_by_id(server->global_list,
3792 /* Check whether target client is on the channel */
3793 if (!silc_server_client_on_channel(target_client, channel)) {
3794 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3795 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3799 /* Get entry to the channel user list */
3800 silc_list_start(channel->user_list);
3801 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3802 if (chl->client == target_client)
3809 /* If the target client is founder, no one else can change their mode
3811 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3813 SILC_STATUS_ERR_NOT_YOU);
3817 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3818 /* Cannot promote anyone to channel founder */
3819 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3820 SILC_STATUS_ERR_NOT_YOU);
3823 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3824 if (target_client == client) {
3825 /* Remove channel founder rights from itself */
3826 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3829 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3830 SILC_STATUS_ERR_NOT_YOU);
3836 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3837 /* Promote to operator */
3838 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3839 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3843 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3844 /* Demote to normal user */
3845 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3850 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3852 /* Send notify to channel, notify only if mode was actually changed. */
3854 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3855 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3856 idp->data, idp->len,
3860 /* Set CUMODE notify type to network */
3861 if (!server->standalone)
3862 silc_server_send_notify_cumode(server, server->router->connection,
3863 server->server_type == SILC_ROUTER ?
3864 TRUE : FALSE, channel,
3865 target_mask, client->id,
3868 SILC_ID_CLIENT_LEN);
3871 /* Send command reply to sender */
3872 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3873 SILC_STATUS_OK, ident, 2,
3875 3, tmp_id, tmp_len);
3876 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3877 packet->data, packet->len, FALSE);
3879 silc_buffer_free(packet);
3880 silc_free(channel_id);
3881 silc_free(client_id);
3882 silc_buffer_free(idp);
3885 silc_server_command_free(cmd);
3888 /* Server side of KICK command. Kicks client out of channel. */
3890 SILC_SERVER_CMD_FUNC(kick)
3892 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3893 SilcServer server = cmd->server;
3894 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3895 SilcClientEntry target_client;
3896 SilcChannelID *channel_id;
3897 SilcClientID *client_id;
3898 SilcChannelEntry channel;
3899 SilcChannelClientEntry chl;
3901 unsigned int tmp_len;
3902 unsigned char *tmp, *comment;
3904 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3906 /* Get Channel ID */
3907 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3909 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3910 SILC_STATUS_ERR_NO_CHANNEL_ID);
3913 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3915 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3916 SILC_STATUS_ERR_NO_CHANNEL_ID);
3920 /* Get channel entry */
3921 channel = silc_idlist_find_channel_by_id(server->local_list,
3924 channel = silc_idlist_find_channel_by_id(server->local_list,
3927 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3928 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3933 /* Check whether sender is on the channel */
3934 if (!silc_server_client_on_channel(client, channel)) {
3935 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3936 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3940 /* Check that the kicker is channel operator or channel founder */
3941 silc_list_start(channel->user_list);
3942 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3943 if (chl->client == client) {
3944 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3945 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3946 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3953 /* Get target Client ID */
3954 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3956 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3957 SILC_STATUS_ERR_NO_CLIENT_ID);
3960 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3963 SILC_STATUS_ERR_NO_CLIENT_ID);
3967 /* Get target client's entry */
3968 target_client = silc_idlist_find_client_by_id(server->local_list,
3970 if (!target_client) {
3971 target_client = silc_idlist_find_client_by_id(server->global_list,
3975 /* Check that the target client is not channel founder. Channel founder
3976 cannot be kicked from the channel. */
3977 silc_list_start(channel->user_list);
3978 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3979 if (chl->client == target_client) {
3980 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3982 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3989 /* Check whether target client is on the channel */
3990 if (!silc_server_client_on_channel(target_client, channel)) {
3991 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3992 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3998 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4002 /* Send command reply to sender */
4003 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4006 /* Send KICKED notify to local clients on the channel */
4007 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4008 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4009 SILC_NOTIFY_TYPE_KICKED,
4011 idp->data, idp->len,
4012 comment, comment ? strlen(comment) : 0);
4013 silc_buffer_free(idp);
4015 /* Remove the client from the channel. If the channel does not exist
4016 after removing the client then the client kicked itself off the channel
4017 and we don't have to send anything after that. */
4018 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4019 target_client, FALSE))
4022 /* Send KICKED notify to primary route */
4023 if (!server->standalone)
4024 silc_server_send_notify_kicked(server, server->router->connection,
4025 server->server_type == SILC_ROUTER ?
4026 TRUE : FALSE, channel,
4027 target_client->id, SILC_ID_CLIENT_LEN,
4030 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4031 /* Re-generate channel key */
4032 silc_server_create_channel_key(server, channel, 0);
4034 /* Send the channel key to the channel. The key of course is not sent
4035 to the client who was kicked off the channel. */
4036 silc_server_send_channel_key(server, target_client->connection, channel,
4037 server->server_type == SILC_ROUTER ?
4038 FALSE : !server->standalone);
4042 silc_server_command_free(cmd);
4045 /* Server side of OPER command. Client uses this comand to obtain server
4046 operator privileges to this server/router. */
4048 SILC_SERVER_CMD_FUNC(oper)
4050 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4051 SilcServer server = cmd->server;
4052 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4053 unsigned char *username, *auth;
4054 unsigned int tmp_len;
4055 SilcServerConfigSectionAdminConnection *admin;
4056 SilcIDListData idata = (SilcIDListData)client;
4058 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
4060 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4063 /* Get the username */
4064 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4066 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4067 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4071 /* Get the admin configuration */
4072 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4073 username, client->nickname);
4075 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4076 username, client->nickname);
4078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4079 SILC_STATUS_ERR_AUTH_FAILED);
4084 /* Get the authentication payload */
4085 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4087 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4088 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4092 /* Verify the authentication data */
4093 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4094 admin->auth_data, admin->auth_data_len,
4095 idata->hash, client->id, SILC_ID_CLIENT)) {
4096 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4097 SILC_STATUS_ERR_AUTH_FAILED);
4101 /* Client is now server operator */
4102 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4104 /* Send UMODE change to primary router */
4105 if (!server->standalone)
4106 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4107 client->id, SILC_ID_CLIENT_LEN,
4110 /* Send reply to the sender */
4111 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4115 silc_server_command_free(cmd);
4118 /* Server side of SILCOPER command. Client uses this comand to obtain router
4119 operator privileges to this router. */
4121 SILC_SERVER_CMD_FUNC(silcoper)
4123 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4124 SilcServer server = cmd->server;
4125 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4126 unsigned char *username, *auth;
4127 unsigned int tmp_len;
4128 SilcServerConfigSectionAdminConnection *admin;
4129 SilcIDListData idata = (SilcIDListData)client;
4131 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4133 if (server->server_type == SILC_SERVER)
4136 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4139 /* Get the username */
4140 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4142 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4143 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4147 /* Get the admin configuration */
4148 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4149 username, client->nickname);
4151 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4152 username, client->nickname);
4154 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4155 SILC_STATUS_ERR_AUTH_FAILED);
4160 /* Get the authentication payload */
4161 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4163 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4164 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4168 /* Verify the authentication data */
4169 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4170 admin->auth_data, admin->auth_data_len,
4171 idata->hash, client->id, SILC_ID_CLIENT)) {
4172 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4173 SILC_STATUS_ERR_AUTH_FAILED);
4177 /* Client is now router operator */
4178 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4180 /* Send UMODE change to primary router */
4181 if (!server->standalone)
4182 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4183 client->id, SILC_ID_CLIENT_LEN,
4186 /* Send reply to the sender */
4187 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4191 silc_server_command_free(cmd);
4194 /* Server side command of CONNECT. Connects us to the specified remote
4195 server or router. */
4197 SILC_SERVER_CMD_FUNC(connect)
4199 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4200 SilcServer server = cmd->server;
4201 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4202 unsigned char *tmp, *host;
4203 unsigned int tmp_len;
4204 unsigned int port = SILC_PORT;
4206 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4208 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4211 /* Check whether client has the permissions. */
4212 if (client->mode == SILC_UMODE_NONE) {
4213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4214 SILC_STATUS_ERR_NO_SERVER_PRIV);
4218 if (server->server_type == SILC_ROUTER &&
4219 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4220 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4221 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4225 /* Get the remote server */
4226 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4228 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4229 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4234 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4236 SILC_GET32_MSB(port, tmp);
4238 /* Create the connection. It is done with timeout and is async. */
4239 silc_server_create_connection(server, host, port);
4241 /* Send reply to the sender */
4242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4246 silc_server_command_free(cmd);
4249 SILC_SERVER_CMD_FUNC(restart)
4251 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4253 silc_server_command_free(cmd);
4256 /* Server side command of CLOSE. Closes connection to a specified server. */
4258 SILC_SERVER_CMD_FUNC(close)
4260 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4261 SilcServer server = cmd->server;
4262 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4263 SilcServerEntry server_entry;
4264 SilcSocketConnection sock;
4266 unsigned int tmp_len;
4267 unsigned char *name;
4268 unsigned int port = SILC_PORT;
4270 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4272 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4275 /* Check whether client has the permissions. */
4276 if (client->mode == SILC_UMODE_NONE) {
4277 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4278 SILC_STATUS_ERR_NO_SERVER_PRIV);
4282 /* Get the remote server */
4283 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4286 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4291 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4293 SILC_GET32_MSB(port, tmp);
4295 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4297 if (!server_entry) {
4298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4299 SILC_STATUS_ERR_NO_SERVER_ID);
4303 /* Send reply to the sender */
4304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4307 /* Close the connection to the server */
4308 sock = (SilcSocketConnection)server_entry->connection;
4309 silc_server_free_sock_user_data(server, sock);
4310 silc_server_close_connection(server, sock);
4313 silc_server_command_free(cmd);
4316 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4317 active connections. */
4319 SILC_SERVER_CMD_FUNC(shutdown)
4321 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4322 SilcServer server = cmd->server;
4323 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4325 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4327 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4330 /* Check whether client has the permission. */
4331 if (client->mode == SILC_UMODE_NONE) {
4332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4333 SILC_STATUS_ERR_NO_SERVER_PRIV);
4337 /* Send reply to the sender */
4338 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4341 /* Then, gracefully, or not, bring the server down. */
4342 silc_server_stop(server);
4346 silc_server_command_free(cmd);
4349 /* Server side command of LEAVE. Removes client from a channel. */
4351 SILC_SERVER_CMD_FUNC(leave)
4353 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4354 SilcServer server = cmd->server;
4355 SilcSocketConnection sock = cmd->sock;
4356 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4358 SilcChannelEntry channel;
4362 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4364 /* Get Channel ID */
4365 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4367 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4368 SILC_STATUS_ERR_NO_CHANNEL_ID);
4371 id = silc_id_payload_parse_id(tmp, len);
4373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4374 SILC_STATUS_ERR_NO_CHANNEL_ID);
4378 /* Get channel entry */
4379 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4381 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4384 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4389 /* Check whether this client is on the channel */
4390 if (!silc_server_client_on_channel(id_entry, channel)) {
4391 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4392 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4396 /* Notify routers that they should remove this client from their list
4397 of clients on the channel. Send LEAVE notify type. */
4398 if (!server->standalone)
4399 silc_server_send_notify_leave(server, server->router->connection,
4400 server->server_type == SILC_ROUTER ?
4401 TRUE : FALSE, channel, id_entry->id,
4402 SILC_ID_CLIENT_LEN);
4404 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4407 /* Remove client from channel */
4408 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4410 /* If the channel does not exist anymore we won't send anything */
4413 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4414 /* Re-generate channel key */
4415 silc_server_create_channel_key(server, channel, 0);
4417 /* Send the channel key */
4418 silc_server_send_channel_key(server, NULL, channel,
4419 server->server_type == SILC_ROUTER ?
4420 FALSE : !server->standalone);
4426 silc_server_command_free(cmd);
4429 /* Server side of command USERS. Resolves clients and their USERS currently
4430 joined on the requested channel. The list of Client ID's and their modes
4431 on the channel is sent back. */
4433 SILC_SERVER_CMD_FUNC(users)
4435 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4436 SilcServer server = cmd->server;
4437 SilcChannelEntry channel;
4440 unsigned char *channel_id;
4441 unsigned int channel_id_len;
4442 SilcBuffer client_id_list;
4443 SilcBuffer client_mode_list;
4444 unsigned char lc[4];
4445 unsigned int list_count = 0;
4446 unsigned short ident = silc_command_get_ident(cmd->payload);
4448 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4450 /* Get Channel ID */
4451 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4454 SILC_STATUS_ERR_NO_CHANNEL_ID);
4457 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4459 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4460 SILC_STATUS_ERR_NO_CHANNEL_ID);
4464 /* If we are server and we don't know about this channel we will send
4465 the command to our router. If we know about the channel then we also
4466 have the list of users already. */
4467 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4469 if (server->server_type == SILC_SERVER && !server->standalone &&
4473 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4474 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4476 /* Send USERS command */
4477 silc_server_packet_send(server, server->router->connection,
4478 SILC_PACKET_COMMAND, cmd->packet->flags,
4479 tmpbuf->data, tmpbuf->len, TRUE);
4481 /* Reprocess this packet after received reply */
4482 silc_server_command_pending(server, SILC_COMMAND_USERS,
4483 silc_command_get_ident(cmd->payload),
4484 silc_server_command_destructor,
4485 silc_server_command_users,
4486 silc_server_command_dup(cmd));
4487 cmd->pending = TRUE;
4488 silc_command_set_ident(cmd->payload, ident);
4490 silc_buffer_free(tmpbuf);
4495 /* We are router and we will check the global list as well. */
4496 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4498 /* Channel really does not exist */
4499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4500 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4505 /* Get the users list */
4506 silc_server_get_users_on_channel(server, channel, &client_id_list,
4507 &client_mode_list, &list_count);
4510 SILC_PUT32_MSB(list_count, lc);
4513 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4514 SILC_STATUS_OK, ident, 4,
4515 2, channel_id, channel_id_len,
4517 4, client_id_list->data,
4518 client_id_list->len,
4519 5, client_mode_list->data,
4520 client_mode_list->len);
4521 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4522 packet->data, packet->len, FALSE);
4524 silc_buffer_free(packet);
4525 silc_buffer_free(client_id_list);
4526 silc_buffer_free(client_mode_list);
4530 silc_server_command_free(cmd);
4533 /* Server side of command BAN. This is used to manage the ban list of the
4534 channel. To add clients and remove clients from the ban list. */
4536 SILC_SERVER_CMD_FUNC(ban)
4538 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4539 SilcServer server = cmd->server;
4540 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4542 SilcChannelEntry channel;
4543 SilcChannelClientEntry chl;
4544 SilcChannelID *channel_id = NULL;
4545 unsigned char *id, *add, *del;
4546 unsigned int id_len, tmp_len;
4547 unsigned short ident = silc_command_get_ident(cmd->payload);
4549 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4552 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4554 /* Get Channel ID */
4555 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4557 channel_id = silc_id_payload_parse_id(id, id_len);
4559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4560 SILC_STATUS_ERR_NO_CHANNEL_ID);
4565 /* Get channel entry. The server must know about the channel since the
4566 client is expected to be on the channel. */
4567 channel = silc_idlist_find_channel_by_id(server->local_list,
4570 channel = silc_idlist_find_channel_by_id(server->global_list,
4573 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4574 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4579 /* Check whether this client is on the channel */
4580 if (!silc_server_client_on_channel(client, channel)) {
4581 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4582 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4586 /* Get entry to the channel user list */
4587 silc_list_start(channel->user_list);
4588 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4589 if (chl->client == client)
4592 /* The client must be at least channel operator. */
4593 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4594 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4595 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4599 /* Get the new ban and add it to the ban list */
4600 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4602 if (!channel->ban_list)
4603 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4605 channel->ban_list = silc_realloc(channel->ban_list,
4606 sizeof(*channel->ban_list) *
4608 strlen(channel->ban_list) + 2));
4609 if (add[tmp_len - 1] == ',')
4610 add[tmp_len - 1] = '\0';
4612 strncat(channel->ban_list, add, tmp_len);
4613 strncat(channel->ban_list, ",", 1);
4616 /* Get the ban to be removed and remove it from the list */
4617 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4618 if (del && channel->ban_list) {
4619 char *start, *end, *n;
4621 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4622 silc_free(channel->ban_list);
4623 channel->ban_list = NULL;
4625 start = strstr(channel->ban_list, del);
4626 if (start && strlen(start) >= tmp_len) {
4627 end = start + tmp_len;
4628 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4629 strncat(n, channel->ban_list, start - channel->ban_list);
4630 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4632 silc_free(channel->ban_list);
4633 channel->ban_list = n;
4638 /* Send the BAN notify type to our primary router. */
4639 if (!server->standalone && (add || del))
4640 silc_server_send_notify_ban(server, server->router->connection,
4641 server->server_type == SILC_ROUTER ?
4642 TRUE : FALSE, channel, add, del);
4644 /* Send the reply back to the client */
4645 if (channel->ban_list)
4647 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4648 SILC_STATUS_OK, ident, 2,
4650 3, channel->ban_list,
4651 strlen(channel->ban_list) - 1);
4654 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4655 SILC_STATUS_OK, ident, 1,
4658 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4659 packet->data, packet->len, FALSE);
4661 silc_buffer_free(packet);
4665 silc_free(channel_id);
4666 silc_server_command_free(cmd);