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)
533 SilcServer server = cmd->server;
535 int i, count = 0, len;
536 SilcBuffer packet, idp, channels;
537 SilcClientEntry entry;
538 SilcCommandStatus status;
539 unsigned short ident = silc_command_get_ident(cmd->payload);
540 char nh[128], uh[128];
541 unsigned char idle[4], mode[4];
542 SilcSocketConnection hsock;
544 status = SILC_STATUS_OK;
545 if (clients_count > 1)
546 status = SILC_STATUS_LIST_START;
548 for (i = 0; i < clients_count; i++) {
551 if (entry->data.registered == FALSE) {
552 if (clients_count == 1) {
553 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
554 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
555 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
556 2, idp->data, idp->len);
557 silc_buffer_free(idp);
562 if (count && i - 1 == count)
566 status = SILC_STATUS_LIST_ITEM;
568 if (clients_count > 1 && i == clients_count - 1)
569 status = SILC_STATUS_LIST_END;
571 /* Sanity check, however these should never fail. However, as
572 this sanity check has been added here they have failed. */
573 if (!entry->nickname || !entry->username || !entry->userinfo)
576 /* Send WHOIS reply */
577 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
578 tmp = silc_argument_get_first_arg(cmd->args, NULL);
580 memset(uh, 0, sizeof(uh));
581 memset(nh, 0, sizeof(nh));
582 memset(idle, 0, sizeof(idle));
584 strncat(nh, entry->nickname, strlen(entry->nickname));
585 if (!strchr(entry->nickname, '@')) {
587 len = entry->router ? strlen(entry->router->server_name) :
588 strlen(server->server_name);
589 strncat(nh, entry->router ? entry->router->server_name :
590 server->server_name, len);
593 strncat(uh, entry->username, strlen(entry->username));
594 if (!strchr(entry->username, '@')) {
596 hsock = (SilcSocketConnection)entry->connection;
597 len = strlen(hsock->hostname);
598 strncat(uh, hsock->hostname, len);
601 channels = silc_server_get_client_channel_list(server, entry);
603 SILC_PUT32_MSB(entry->mode, mode);
605 if (entry->connection) {
606 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
610 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
612 2, idp->data, idp->len,
616 strlen(entry->userinfo),
622 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
624 2, idp->data, idp->len,
628 strlen(entry->userinfo),
632 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
633 0, packet->data, packet->len, FALSE);
635 silc_buffer_free(packet);
636 silc_buffer_free(idp);
638 silc_buffer_free(channels);
643 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
645 SilcServer server = cmd->server;
646 char *nick = NULL, *server_name = NULL;
647 int count = 0, clients_count = 0;
648 SilcClientEntry *clients = NULL, entry;
649 SilcClientID **client_id = NULL;
650 unsigned int client_id_count = 0;
653 /* Protocol dictates that we must always send the received WHOIS request
654 to our router if we are normal server, so let's do it now unless we
655 are standalone. We will not send any replies to the client until we
656 have received reply from the router. */
657 if (server->server_type == SILC_SERVER && !cmd->pending &&
658 !server->standalone) {
660 unsigned short old_ident;
662 old_ident = silc_command_get_ident(cmd->payload);
663 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
664 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
666 /* Send WHOIS command to our router */
667 silc_server_packet_send(server, (SilcSocketConnection)
668 server->router->connection,
669 SILC_PACKET_COMMAND, cmd->packet->flags,
670 tmpbuf->data, tmpbuf->len, TRUE);
672 /* Reprocess this packet after received reply from router */
673 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
674 silc_command_get_ident(cmd->payload),
675 silc_server_command_destructor,
676 silc_server_command_whois,
677 silc_server_command_dup(cmd));
680 silc_command_set_ident(cmd->payload, old_ident);
682 silc_buffer_free(tmpbuf);
687 /* We are ready to process the command request. Let's search for the
688 requested client and send reply to the requesting client. */
690 /* Parse the whois request */
691 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
692 &nick, &server_name, &count,
696 /* Get all clients matching that ID or nickname from local list */
697 if (client_id_count) {
698 /* Check all Client ID's received in the command packet */
699 for (i = 0; i < client_id_count; i++) {
700 entry = silc_idlist_find_client_by_id(server->local_list,
703 clients = silc_realloc(clients, sizeof(*clients) *
704 (clients_count + 1));
705 clients[clients_count++] = entry;
709 clients = silc_idlist_get_clients_by_hash(server->local_list,
710 nick, server->md5hash,
713 clients = silc_idlist_get_clients_by_nickname(server->local_list,
718 /* Check global list as well */
720 if (client_id_count) {
721 /* Check all Client ID's received in the command packet */
722 for (i = 0; i < client_id_count; i++) {
723 entry = silc_idlist_find_client_by_id(server->global_list,
726 clients = silc_realloc(clients, sizeof(*clients) *
727 (clients_count + 1));
728 clients[clients_count++] = entry;
732 clients = silc_idlist_get_clients_by_hash(server->global_list,
733 nick, server->md5hash,
736 clients = silc_idlist_get_clients_by_nickname(server->global_list,
743 /* Such client(s) really does not exist in the SILC network. */
744 if (!client_id_count) {
745 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
746 SILC_STATUS_ERR_NO_SUCH_NICK,
747 3, nick, strlen(nick));
749 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
750 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
751 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
752 2, idp->data, idp->len);
753 silc_buffer_free(idp);
758 /* Router always finds the client entry if it exists in the SILC network.
759 However, it might be incomplete entry and does not include all the
760 mandatory fields that WHOIS command reply requires. Check for these and
761 make query from the server who owns the client if some fields are
763 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
768 /* Send the command reply to the client */
769 silc_server_command_whois_send_reply(cmd, clients, clients_count);
772 if (client_id_count) {
773 for (i = 0; i < client_id_count; i++)
774 silc_free(client_id[i]);
775 silc_free(client_id);
782 silc_free(server_name);
788 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
790 SilcServer server = cmd->server;
791 char *nick = NULL, *server_name = NULL;
792 int count = 0, clients_count = 0;
793 SilcClientEntry *clients = NULL, entry;
794 SilcClientID **client_id = NULL;
795 unsigned int client_id_count = 0;
798 /* Parse the whois request */
799 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
800 &nick, &server_name, &count,
804 /* Process the command request. Let's search for the requested client and
805 send reply to the requesting server. */
807 if (client_id_count) {
808 /* Check all Client ID's received in the command packet */
809 for (i = 0; i < client_id_count; i++) {
810 entry = silc_idlist_find_client_by_id(server->local_list,
813 clients = silc_realloc(clients, sizeof(*clients) *
814 (clients_count + 1));
815 clients[clients_count++] = entry;
819 clients = silc_idlist_get_clients_by_hash(server->local_list,
820 nick, server->md5hash,
823 clients = silc_idlist_get_clients_by_nickname(server->local_list,
828 /* If we are router we will check our global list as well. */
829 if (!clients && server->server_type == SILC_ROUTER) {
830 if (client_id_count) {
831 /* Check all Client ID's received in the command packet */
832 for (i = 0; i < client_id_count; i++) {
833 entry = silc_idlist_find_client_by_id(server->global_list,
836 clients = silc_realloc(clients, sizeof(*clients) *
837 (clients_count + 1));
838 clients[clients_count++] = entry;
842 clients = silc_idlist_get_clients_by_hash(server->global_list,
843 nick, server->md5hash,
846 clients = silc_idlist_get_clients_by_nickname(server->global_list,
853 /* Such a client really does not exist in the SILC network. */
854 if (!client_id_count) {
855 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
856 SILC_STATUS_ERR_NO_SUCH_NICK,
857 3, nick, strlen(nick));
859 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
860 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
861 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
862 2, idp->data, idp->len);
863 silc_buffer_free(idp);
868 /* Router always finds the client entry if it exists in the SILC network.
869 However, it might be incomplete entry and does not include all the
870 mandatory fields that WHOIS command reply requires. Check for these and
871 make query from the server who owns the client if some fields are
873 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
878 /* Send the command reply to the client */
879 silc_server_command_whois_send_reply(cmd, clients, clients_count);
882 if (client_id_count) {
883 for (i = 0; i < client_id_count; i++)
884 silc_free(client_id[i]);
885 silc_free(client_id);
892 silc_free(server_name);
897 /* Server side of command WHOIS. Processes user's query and sends found
898 results as command replies back to the client. */
900 SILC_SERVER_CMD_FUNC(whois)
902 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
905 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
907 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
908 ret = silc_server_command_whois_from_client(cmd);
909 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
910 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
911 ret = silc_server_command_whois_from_server(cmd);
914 silc_server_command_free(cmd);
917 /******************************************************************************
921 ******************************************************************************/
924 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
932 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
934 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
935 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
939 /* Get the nickname@server string and parse it. */
940 if (strchr(tmp, '@')) {
941 len = strcspn(tmp, "@");
942 *nickname = silc_calloc(len + 1, sizeof(char));
943 memcpy(*nickname, tmp, len);
944 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
945 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
947 *nickname = strdup(tmp);
949 /* Get the max count of reply messages allowed */
950 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
960 silc_server_command_whowas_check(SilcServerCommandContext cmd,
961 SilcClientEntry *clients,
962 unsigned int clients_count)
964 SilcServer server = cmd->server;
966 SilcClientEntry entry;
968 for (i = 0; i < clients_count; i++) {
971 if (!entry->nickname || !entry->username) {
973 unsigned short old_ident;
978 old_ident = silc_command_get_ident(cmd->payload);
979 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
980 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
982 /* Send WHOWAS command */
983 silc_server_packet_send(server, entry->router->connection,
984 SILC_PACKET_COMMAND, cmd->packet->flags,
985 tmpbuf->data, tmpbuf->len, TRUE);
987 /* Reprocess this packet after received reply */
988 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
989 silc_command_get_ident(cmd->payload),
990 silc_server_command_destructor,
991 silc_server_command_whowas,
992 silc_server_command_dup(cmd));
995 silc_command_set_ident(cmd->payload, old_ident);
997 silc_buffer_free(tmpbuf);
1006 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1007 SilcClientEntry *clients,
1008 unsigned int clients_count)
1010 SilcServer server = cmd->server;
1012 int i, count = 0, len;
1013 SilcBuffer packet, idp;
1014 SilcClientEntry entry = NULL;
1015 SilcCommandStatus status;
1016 unsigned short ident = silc_command_get_ident(cmd->payload);
1018 char nh[256], uh[256];
1020 status = SILC_STATUS_OK;
1021 if (clients_count > 1)
1022 status = SILC_STATUS_LIST_START;
1024 for (i = 0; i < clients_count; i++) {
1027 /* We will take only clients that are not valid anymore. They are the
1028 ones that are not registered anymore but still have a ID. They
1029 have disconnected us, and thus valid for WHOWAS. */
1030 if (entry->data.registered == TRUE)
1032 if (entry->id == NULL)
1035 if (count && i - 1 == count)
1040 if (clients_count > 2)
1041 status = SILC_STATUS_LIST_ITEM;
1043 if (clients_count > 1 && i == clients_count - 1)
1044 status = SILC_STATUS_LIST_END;
1046 /* Sanity check, however these should never fail. However, as
1047 this sanity check has been added here they have failed. */
1048 if (!entry->nickname || !entry->username)
1051 /* Send WHOWAS reply */
1052 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1053 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1055 memset(uh, 0, sizeof(uh));
1056 memset(nh, 0, sizeof(nh));
1058 strncat(nh, entry->nickname, strlen(entry->nickname));
1059 if (!strchr(entry->nickname, '@')) {
1060 strncat(nh, "@", 1);
1061 len = entry->router ? strlen(entry->router->server_name) :
1062 strlen(server->server_name);
1063 strncat(nh, entry->router ? entry->router->server_name :
1064 server->server_name, len);
1067 strncat(uh, entry->username, strlen(entry->username));
1068 if (!strchr(entry->username, '@')) {
1069 strncat(uh, "@", 1);
1070 strcat(uh, "*private*");
1073 if (entry->userinfo)
1075 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1077 2, idp->data, idp->len,
1081 strlen(entry->userinfo));
1084 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1086 2, idp->data, idp->len,
1090 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1091 0, packet->data, packet->len, FALSE);
1093 silc_buffer_free(packet);
1094 silc_buffer_free(idp);
1097 if (found == FALSE && entry)
1098 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1099 SILC_STATUS_ERR_NO_SUCH_NICK,
1101 strlen(entry->nickname));
1105 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1107 SilcServer server = cmd->server;
1108 char *nick = NULL, *server_name = NULL;
1109 int count = 0, clients_count = 0;
1110 SilcClientEntry *clients = NULL;
1113 /* Protocol dictates that we must always send the received WHOWAS request
1114 to our router if we are normal server, so let's do it now unless we
1115 are standalone. We will not send any replies to the client until we
1116 have received reply from the router. */
1117 if (server->server_type == SILC_SERVER &&
1118 !cmd->pending && !server->standalone) {
1120 unsigned short old_ident;
1122 old_ident = silc_command_get_ident(cmd->payload);
1123 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1124 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1126 /* Send WHOWAS command to our router */
1127 silc_server_packet_send(server, (SilcSocketConnection)
1128 server->router->connection,
1129 SILC_PACKET_COMMAND, cmd->packet->flags,
1130 tmpbuf->data, tmpbuf->len, TRUE);
1132 /* Reprocess this packet after received reply from router */
1133 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1134 silc_command_get_ident(cmd->payload),
1135 silc_server_command_destructor,
1136 silc_server_command_whowas,
1137 silc_server_command_dup(cmd));
1138 cmd->pending = TRUE;
1140 silc_command_set_ident(cmd->payload, old_ident);
1142 silc_buffer_free(tmpbuf);
1147 /* We are ready to process the command request. Let's search for the
1148 requested client and send reply to the requesting client. */
1150 /* Parse the whowas request */
1151 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1154 /* Get all clients matching that nickname from local list */
1155 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1159 clients = silc_idlist_get_clients_by_hash(server->local_list,
1160 nick, server->md5hash,
1163 /* Check global list as well */
1165 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1169 clients = silc_idlist_get_clients_by_hash(server->global_list,
1170 nick, server->md5hash,
1174 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1179 /* Send the command reply to the client */
1180 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1188 silc_free(server_name);
1194 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1196 SilcServer server = cmd->server;
1197 char *nick = NULL, *server_name = NULL;
1198 int count = 0, clients_count = 0;
1199 SilcClientEntry *clients = NULL;
1202 /* Parse the whowas request */
1203 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1206 /* Process the command request. Let's search for the requested client and
1207 send reply to the requesting server. */
1209 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1213 clients = silc_idlist_get_clients_by_hash(server->local_list,
1214 nick, server->md5hash,
1217 /* If we are router we will check our global list as well. */
1218 if (!clients && server->server_type == SILC_ROUTER) {
1219 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1223 clients = silc_idlist_get_clients_by_hash(server->global_list,
1224 nick, server->md5hash,
1229 /* Such a client really does not exist in the SILC network. */
1230 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1231 SILC_STATUS_ERR_NO_SUCH_NICK,
1232 3, nick, strlen(nick));
1236 /* Send the command reply to the client */
1237 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1245 silc_free(server_name);
1250 /* Server side of command WHOWAS. */
1252 SILC_SERVER_CMD_FUNC(whowas)
1254 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1257 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1259 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1260 ret = silc_server_command_whowas_from_client(cmd);
1261 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1262 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1263 ret = silc_server_command_whowas_from_server(cmd);
1266 silc_server_command_free(cmd);
1269 /******************************************************************************
1273 ******************************************************************************/
1275 /* Checks that all mandatory fields are present. If not then send WHOIS
1276 request to the server who owns the client. We use WHOIS because we want
1277 to get as much information as possible at once. */
1280 silc_server_command_identify_check(SilcServerCommandContext cmd,
1281 SilcClientEntry *clients,
1282 unsigned int clients_count)
1284 SilcServer server = cmd->server;
1286 SilcClientEntry entry;
1288 for (i = 0; i < clients_count; i++) {
1291 if (entry->data.registered == FALSE)
1294 if (!entry->nickname) {
1296 unsigned short old_ident;
1301 old_ident = silc_command_get_ident(cmd->payload);
1302 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1303 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1304 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1306 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1307 now anyway so make it a good one. */
1308 silc_server_packet_send(server, entry->router->connection,
1309 SILC_PACKET_COMMAND, cmd->packet->flags,
1310 tmpbuf->data, tmpbuf->len, TRUE);
1312 /* Reprocess this packet after received reply */
1313 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1314 silc_command_get_ident(cmd->payload),
1315 silc_server_command_destructor,
1316 silc_server_command_identify,
1317 silc_server_command_dup(cmd));
1319 cmd->pending = TRUE;
1321 /* Put old data back to the Command Payload we just changed */
1322 silc_command_set_ident(cmd->payload, old_ident);
1323 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1325 silc_buffer_free(tmpbuf);
1334 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1335 SilcClientEntry *clients,
1336 unsigned int clients_count)
1338 SilcServer server = cmd->server;
1340 int i, count = 0, len;
1341 SilcBuffer packet, idp;
1342 SilcClientEntry entry;
1343 SilcCommandStatus status;
1344 unsigned short ident = silc_command_get_ident(cmd->payload);
1345 char nh[256], uh[256];
1346 SilcSocketConnection hsock;
1348 status = SILC_STATUS_OK;
1349 if (clients_count > 1)
1350 status = SILC_STATUS_LIST_START;
1352 for (i = 0; i < clients_count; i++) {
1355 if (entry->data.registered == FALSE) {
1356 if (clients_count == 1) {
1357 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1358 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1359 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1360 2, idp->data, idp->len);
1361 silc_buffer_free(idp);
1366 if (count && i - 1 == count)
1370 status = SILC_STATUS_LIST_ITEM;
1372 if (clients_count > 1 && i == clients_count - 1)
1373 status = SILC_STATUS_LIST_END;
1375 /* Send IDENTIFY reply */
1376 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1377 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1379 memset(uh, 0, sizeof(uh));
1380 memset(nh, 0, sizeof(nh));
1382 strncat(nh, entry->nickname, strlen(entry->nickname));
1383 if (!strchr(entry->nickname, '@')) {
1384 strncat(nh, "@", 1);
1385 len = entry->router ? strlen(entry->router->server_name) :
1386 strlen(server->server_name);
1387 strncat(nh, entry->router ? entry->router->server_name :
1388 server->server_name, len);
1391 if (!entry->username) {
1392 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1394 2, idp->data, idp->len,
1397 strncat(uh, entry->username, strlen(entry->username));
1398 if (!strchr(entry->username, '@')) {
1399 strncat(uh, "@", 1);
1400 hsock = (SilcSocketConnection)entry->connection;
1401 len = strlen(hsock->hostname);
1402 strncat(uh, hsock->hostname, len);
1405 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1407 2, idp->data, idp->len,
1412 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1413 0, packet->data, packet->len, FALSE);
1415 silc_buffer_free(packet);
1416 silc_buffer_free(idp);
1421 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1423 SilcServer server = cmd->server;
1424 char *nick = NULL, *server_name = NULL;
1425 int count = 0, clients_count = 0;
1426 SilcClientEntry *clients = NULL, entry;
1427 SilcClientID **client_id = NULL;
1428 unsigned int client_id_count = 0;
1431 /* Protocol dictates that we must always send the received IDENTIFY request
1432 to our router if we are normal server, so let's do it now unless we
1433 are standalone. We will not send any replies to the client until we
1434 have received reply from the router. */
1435 if (server->server_type == SILC_SERVER &&
1436 !cmd->pending && !server->standalone) {
1438 unsigned short old_ident;
1440 old_ident = silc_command_get_ident(cmd->payload);
1441 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1442 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1444 /* Send IDENTIFY command to our router */
1445 silc_server_packet_send(server, (SilcSocketConnection)
1446 server->router->connection,
1447 SILC_PACKET_COMMAND, cmd->packet->flags,
1448 tmpbuf->data, tmpbuf->len, TRUE);
1450 /* Reprocess this packet after received reply from router */
1451 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1452 silc_command_get_ident(cmd->payload),
1453 silc_server_command_destructor,
1454 silc_server_command_identify,
1455 silc_server_command_dup(cmd));
1456 cmd->pending = TRUE;
1458 silc_command_set_ident(cmd->payload, old_ident);
1460 silc_buffer_free(tmpbuf);
1465 /* We are ready to process the command request. Let's search for the
1466 requested client and send reply to the requesting client. */
1468 /* Parse the IDENTIFY request */
1469 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1470 &nick, &server_name, &count,
1471 SILC_COMMAND_IDENTIFY))
1474 /* Get all clients matching that ID or nickname from local list */
1475 if (client_id_count) {
1476 /* Check all Client ID's received in the command packet */
1477 for (i = 0; i < client_id_count; i++) {
1478 entry = silc_idlist_find_client_by_id(server->local_list,
1479 client_id[i], NULL);
1481 clients = silc_realloc(clients, sizeof(*clients) *
1482 (clients_count + 1));
1483 clients[clients_count++] = entry;
1487 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1491 clients = silc_idlist_get_clients_by_hash(server->local_list,
1492 nick, server->md5hash,
1496 /* Check global list as well */
1498 if (client_id_count) {
1499 /* Check all Client ID's received in the command packet */
1500 for (i = 0; i < client_id_count; i++) {
1501 entry = silc_idlist_find_client_by_id(server->global_list,
1502 client_id[i], NULL);
1504 clients = silc_realloc(clients, sizeof(*clients) *
1505 (clients_count + 1));
1506 clients[clients_count++] = entry;
1510 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1514 clients = silc_idlist_get_clients_by_hash(server->global_list,
1515 nick, server->md5hash,
1521 /* Such a client really does not exist in the SILC network. */
1522 if (!client_id_count) {
1523 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1524 SILC_STATUS_ERR_NO_SUCH_NICK,
1525 3, nick, strlen(nick));
1527 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1528 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1529 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1530 2, idp->data, idp->len);
1531 silc_buffer_free(idp);
1536 /* Check that all mandatory fields are present and request those data
1537 from the server who owns the client if necessary. */
1538 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1543 /* Send the command reply to the client */
1544 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1547 if (client_id_count) {
1548 for (i = 0; i < client_id_count; i++)
1549 silc_free(client_id[i]);
1550 silc_free(client_id);
1557 silc_free(server_name);
1563 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1565 SilcServer server = cmd->server;
1566 char *nick = NULL, *server_name = NULL;
1567 int count = 0, clients_count = 0;
1568 SilcClientEntry *clients = NULL, entry;
1569 SilcClientID **client_id = NULL;
1570 unsigned int client_id_count = 0;
1573 /* Parse the IDENTIFY request */
1574 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1575 &nick, &server_name, &count,
1576 SILC_COMMAND_IDENTIFY))
1579 /* Process the command request. Let's search for the requested client and
1580 send reply to the requesting server. */
1582 if (client_id_count) {
1583 /* Check all Client ID's received in the command packet */
1584 for (i = 0; i < client_id_count; i++) {
1585 entry = silc_idlist_find_client_by_id(server->local_list,
1586 client_id[i], NULL);
1588 clients = silc_realloc(clients, sizeof(*clients) *
1589 (clients_count + 1));
1590 clients[clients_count++] = entry;
1594 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1598 clients = silc_idlist_get_clients_by_hash(server->local_list,
1599 nick, server->md5hash,
1603 /* If we are router we will check our global list as well. */
1604 if (!clients && server->server_type == SILC_ROUTER) {
1605 if (client_id_count) {
1606 /* Check all Client ID's received in the command packet */
1607 for (i = 0; i < client_id_count; i++) {
1608 entry = silc_idlist_find_client_by_id(server->global_list,
1609 client_id[i], NULL);
1611 clients = silc_realloc(clients, sizeof(*clients) *
1612 (clients_count + 1));
1613 clients[clients_count++] = entry;
1617 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1621 clients = silc_idlist_get_clients_by_hash(server->global_list,
1622 nick, server->md5hash,
1628 /* Such a client really does not exist in the SILC network. */
1629 if (!client_id_count) {
1630 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1631 SILC_STATUS_ERR_NO_SUCH_NICK,
1632 3, nick, strlen(nick));
1634 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1635 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1636 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1637 2, idp->data, idp->len);
1638 silc_buffer_free(idp);
1643 /* Check that all mandatory fields are present and request those data
1644 from the server who owns the client if necessary. */
1645 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1650 /* Send the command reply */
1651 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1654 if (client_id_count) {
1655 for (i = 0; i < client_id_count; i++)
1656 silc_free(client_id[i]);
1657 silc_free(client_id);
1664 silc_free(server_name);
1669 SILC_SERVER_CMD_FUNC(identify)
1671 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1674 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1676 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1677 ret = silc_server_command_identify_from_client(cmd);
1678 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1679 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1680 ret = silc_server_command_identify_from_server(cmd);
1683 silc_server_command_free(cmd);
1686 /* Checks string for bad characters and returns TRUE if they are found. */
1688 static int silc_server_command_bad_chars(char *nick)
1690 if (strchr(nick, '\\')) return TRUE;
1691 if (strchr(nick, '\"')) return TRUE;
1692 if (strchr(nick, '´')) return TRUE;
1693 if (strchr(nick, '`')) return TRUE;
1694 if (strchr(nick, '\'')) return TRUE;
1695 if (strchr(nick, '*')) return TRUE;
1696 if (strchr(nick, '/')) return TRUE;
1697 if (strchr(nick, '@')) return TRUE;
1702 /* Server side of command NICK. Sets nickname for user. Setting
1703 nickname causes generation of a new client ID for the client. The
1704 new client ID is sent to the client after changing the nickname. */
1706 SILC_SERVER_CMD_FUNC(nick)
1708 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1709 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1710 SilcServer server = cmd->server;
1711 SilcBuffer packet, nidp, oidp;
1712 SilcClientID *new_id;
1714 unsigned short ident = silc_command_get_ident(cmd->payload);
1716 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1719 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1721 /* Check nickname */
1722 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1723 if (silc_server_command_bad_chars(nick) == TRUE) {
1724 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1725 SILC_STATUS_ERR_BAD_NICKNAME);
1729 if (strlen(nick) > 128)
1732 /* Create new Client ID */
1733 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1734 cmd->server->md5hash, nick,
1737 /* Send notify about nickname change to our router. We send the new
1738 ID and ask to replace it with the old one. If we are router the
1739 packet is broadcasted. Send NICK_CHANGE notify. */
1740 if (!server->standalone)
1741 silc_server_send_notify_nick_change(server, server->router->connection,
1742 server->server_type == SILC_SERVER ?
1743 FALSE : TRUE, client->id,
1744 new_id, SILC_ID_CLIENT_LEN);
1746 /* Remove old cache entry */
1747 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1750 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1754 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1755 silc_free(client->id);
1758 /* Save the nickname as this client is our local client */
1759 if (client->nickname)
1760 silc_free(client->nickname);
1762 client->nickname = strdup(nick);
1763 client->id = new_id;
1765 /* Update client cache */
1766 silc_idcache_add(server->local_list->clients, client->nickname,
1767 strlen(client->nickname), SILC_ID_CLIENT, client->id,
1768 (void *)client, TRUE, FALSE);
1770 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1772 /* Send NICK_CHANGE notify to the client's channels */
1773 silc_server_send_notify_on_channels(server, NULL, client,
1774 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1775 oidp->data, oidp->len,
1776 nidp->data, nidp->len);
1778 /* Send the new Client ID as reply command back to client */
1779 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1780 SILC_STATUS_OK, ident, 1,
1781 2, nidp->data, nidp->len);
1782 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1783 0, packet->data, packet->len, FALSE);
1785 silc_buffer_free(packet);
1786 silc_buffer_free(nidp);
1787 silc_buffer_free(oidp);
1790 silc_server_command_free(cmd);
1793 /* Sends the LIST command reply */
1796 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1797 SilcChannelEntry *lch,
1798 unsigned int lch_count,
1799 SilcChannelEntry *gch,
1800 unsigned int gch_count)
1803 SilcBuffer packet, idp;
1804 SilcChannelEntry entry;
1805 SilcCommandStatus status;
1806 unsigned short ident = silc_command_get_ident(cmd->payload);
1808 unsigned char usercount[4];
1811 for (i = 0; i < lch_count; i++)
1812 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1814 for (i = 0; i < gch_count; i++)
1815 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1818 status = SILC_STATUS_OK;
1819 if ((lch_count + gch_count) > 1)
1820 status = SILC_STATUS_LIST_START;
1823 for (i = 0; i < lch_count; i++) {
1830 status = SILC_STATUS_LIST_ITEM;
1832 if (i == lch_count - 1 && gch_count)
1834 if (lch_count > 1 && i == lch_count - 1)
1835 status = SILC_STATUS_LIST_END;
1837 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1839 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1840 topic = "*private*";
1841 memset(usercount, 0, sizeof(usercount));
1843 topic = entry->topic;
1844 users = silc_list_count(entry->user_list);
1845 SILC_PUT32_MSB(users, usercount);
1848 /* Send the reply */
1851 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1853 2, idp->data, idp->len,
1854 3, entry->channel_name,
1855 strlen(entry->channel_name),
1856 4, topic, strlen(topic),
1860 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1862 2, idp->data, idp->len,
1863 3, entry->channel_name,
1864 strlen(entry->channel_name),
1866 silc_server_packet_send(cmd->server, cmd->sock,
1867 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1868 packet->len, FALSE);
1869 silc_buffer_free(packet);
1870 silc_buffer_free(idp);
1873 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1876 for (i = 0; i < gch_count; i++) {
1883 status = SILC_STATUS_LIST_ITEM;
1885 if (gch_count > 1 && i == lch_count - 1)
1886 status = SILC_STATUS_LIST_END;
1888 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1890 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1891 topic = "*private*";
1892 memset(usercount, 0, sizeof(usercount));
1894 topic = entry->topic;
1895 users = silc_list_count(entry->user_list);
1896 SILC_PUT32_MSB(users, usercount);
1899 /* Send the reply */
1902 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1904 2, idp->data, idp->len,
1905 3, entry->channel_name,
1906 strlen(entry->channel_name),
1907 4, topic, strlen(topic),
1911 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1913 2, idp->data, idp->len,
1914 3, entry->channel_name,
1915 strlen(entry->channel_name),
1917 silc_server_packet_send(cmd->server, cmd->sock,
1918 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1919 packet->len, FALSE);
1920 silc_buffer_free(packet);
1921 silc_buffer_free(idp);
1925 /* Server side of LIST command. This lists the channel of the requested
1926 server. Secret channels are not listed. */
1928 SILC_SERVER_CMD_FUNC(list)
1930 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1931 SilcServer server = cmd->server;
1932 SilcChannelID *channel_id = NULL;
1934 unsigned int tmp_len;
1935 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1936 unsigned int lch_count = 0, gch_count = 0;
1938 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1940 /* Get Channel ID */
1941 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1943 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1945 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1946 SILC_STATUS_ERR_NO_CHANNEL_ID);
1951 /* Get the channels from local list */
1952 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1955 /* Get the channels from global list if we are router */
1956 if (server->server_type == SILC_ROUTER)
1957 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1960 /* Send the reply */
1961 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
1962 gchannels, gch_count);
1965 silc_server_command_free(cmd);
1968 /* Server side of TOPIC command. Sets topic for channel and/or returns
1969 current topic to client. */
1971 SILC_SERVER_CMD_FUNC(topic)
1973 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1974 SilcServer server = cmd->server;
1975 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1976 SilcChannelID *channel_id;
1977 SilcChannelEntry channel;
1978 SilcChannelClientEntry chl;
1979 SilcBuffer packet, idp;
1981 unsigned int argc, tmp_len;
1982 unsigned short ident = silc_command_get_ident(cmd->payload);
1984 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1986 argc = silc_argument_get_arg_num(cmd->args);
1988 /* Get Channel ID */
1989 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1991 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1992 SILC_STATUS_ERR_NO_CHANNEL_ID);
1995 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1998 SILC_STATUS_ERR_NO_CHANNEL_ID);
2002 /* Check whether the channel exists */
2003 channel = silc_idlist_find_channel_by_id(server->local_list,
2006 channel = silc_idlist_find_channel_by_id(server->global_list,
2009 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2010 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2017 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2019 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2020 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2024 if (strlen(tmp) > 256) {
2025 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2026 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2030 /* See whether has rights to change topic */
2031 silc_list_start(channel->user_list);
2032 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2033 if (chl->client == client)
2036 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2037 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2039 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2044 /* Set the topic for channel */
2046 silc_free(channel->topic);
2047 channel->topic = strdup(tmp);
2049 /* Send TOPIC_SET notify type to the network */
2050 if (!server->standalone)
2051 silc_server_send_notify_topic_set(server, server->router->connection,
2052 server->server_type == SILC_ROUTER ?
2053 TRUE : FALSE, channel, client->id,
2054 SILC_ID_CLIENT_LEN, channel->topic);
2056 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2058 /* Send notify about topic change to all clients on the channel */
2059 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2060 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2061 idp->data, idp->len,
2062 channel->topic, strlen(channel->topic));
2063 silc_buffer_free(idp);
2066 /* Send the topic to client as reply packet */
2067 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2069 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2070 SILC_STATUS_OK, ident, 2,
2071 2, idp->data, idp->len,
2073 strlen(channel->topic));
2075 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2076 SILC_STATUS_OK, ident, 1,
2077 2, idp->data, idp->len);
2078 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2079 0, packet->data, packet->len, FALSE);
2081 silc_buffer_free(packet);
2082 silc_buffer_free(idp);
2083 silc_free(channel_id);
2086 silc_server_command_free(cmd);
2089 /* Server side of INVITE command. Invites some client to join some channel.
2090 This command is also used to manage the invite list of the channel. */
2092 SILC_SERVER_CMD_FUNC(invite)
2094 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2095 SilcServer server = cmd->server;
2096 SilcSocketConnection sock = cmd->sock, dest_sock;
2097 SilcChannelClientEntry chl;
2098 SilcClientEntry sender, dest;
2099 SilcClientID *dest_id = NULL;
2100 SilcChannelEntry channel;
2101 SilcChannelID *channel_id = NULL;
2102 SilcIDListData idata;
2103 SilcBuffer idp, idp2, packet;
2104 unsigned char *tmp, *add, *del;
2106 unsigned short ident = silc_command_get_ident(cmd->payload);
2108 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2110 /* Get Channel ID */
2111 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2113 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2114 SILC_STATUS_ERR_NO_CHANNEL_ID);
2117 channel_id = silc_id_payload_parse_id(tmp, len);
2119 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2120 SILC_STATUS_ERR_NO_CHANNEL_ID);
2124 /* Get the channel entry */
2125 channel = silc_idlist_find_channel_by_id(server->local_list,
2128 channel = silc_idlist_find_channel_by_id(server->global_list,
2131 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2132 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2137 /* Check whether the sender of this command is on the channel. */
2138 sender = (SilcClientEntry)sock->user_data;
2139 if (!silc_server_client_on_channel(sender, channel)) {
2140 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2141 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2145 /* Check whether the channel is invite-only channel. If yes then the
2146 sender of this command must be at least channel operator. */
2147 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2148 silc_list_start(channel->user_list);
2149 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2150 if (chl->client == sender) {
2151 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2152 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2153 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2160 /* Get destination client ID */
2161 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2165 dest_id = silc_id_payload_parse_id(tmp, len);
2167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2168 SILC_STATUS_ERR_NO_CLIENT_ID);
2172 /* Get the client entry */
2173 dest = silc_server_get_client_resolve(server, dest_id);
2175 if (server->server_type == SILC_ROUTER) {
2176 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2177 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2181 /* The client info is being resolved. Reprocess this packet after
2182 receiving the reply to the query. */
2183 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2185 silc_server_command_destructor,
2186 silc_server_command_invite,
2187 silc_server_command_dup(cmd));
2188 cmd->pending = TRUE;
2189 silc_free(channel_id);
2194 /* Check whether the requested client is already on the channel. */
2195 if (silc_server_client_on_channel(dest, channel)) {
2196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2197 SILC_STATUS_ERR_USER_ON_CHANNEL);
2201 /* Get route to the client */
2202 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2204 memset(invite, 0, sizeof(invite));
2205 strncat(invite, dest->nickname, strlen(dest->nickname));
2206 strncat(invite, "!", 1);
2207 strncat(invite, dest->username, strlen(dest->username));
2208 if (!strchr(dest->username, '@')) {
2209 strncat(invite, "@", 1);
2210 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2213 len = strlen(invite);
2214 if (!channel->invite_list)
2215 channel->invite_list = silc_calloc(len + 2,
2216 sizeof(*channel->invite_list));
2218 channel->invite_list = silc_realloc(channel->invite_list,
2219 sizeof(*channel->invite_list) *
2221 strlen(channel->invite_list) + 2));
2222 strncat(channel->invite_list, invite, len);
2223 strncat(channel->invite_list, ",", 1);
2225 /* Send notify to the client that is invited to the channel */
2226 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2227 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2228 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2230 SILC_NOTIFY_TYPE_INVITE, 3,
2231 idp->data, idp->len,
2232 channel->channel_name,
2233 strlen(channel->channel_name),
2234 idp2->data, idp2->len);
2235 silc_buffer_free(idp);
2236 silc_buffer_free(idp2);
2239 /* Add the client to the invite list of the channel */
2240 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2242 if (!channel->invite_list)
2243 channel->invite_list = silc_calloc(len + 2,
2244 sizeof(*channel->invite_list));
2246 channel->invite_list = silc_realloc(channel->invite_list,
2247 sizeof(*channel->invite_list) *
2249 strlen(channel->invite_list) + 2));
2250 if (add[len - 1] == ',')
2251 add[len - 1] = '\0';
2253 strncat(channel->invite_list, add, len);
2254 strncat(channel->invite_list, ",", 1);
2257 /* Get the invite to be removed and remove it from the list */
2258 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2259 if (del && channel->invite_list) {
2260 char *start, *end, *n;
2262 if (!strncmp(channel->invite_list, del,
2263 strlen(channel->invite_list) - 1)) {
2264 silc_free(channel->invite_list);
2265 channel->invite_list = NULL;
2267 start = strstr(channel->invite_list, del);
2268 if (start && strlen(start) >= len) {
2270 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2271 strncat(n, channel->invite_list, start - channel->invite_list);
2272 strncat(n, end + 1, ((channel->invite_list +
2273 strlen(channel->invite_list)) - end) - 1);
2274 silc_free(channel->invite_list);
2275 channel->invite_list = n;
2280 /* Send notify to the primary router */
2281 if (!server->standalone)
2282 silc_server_send_notify_invite(server, server->router->connection,
2283 server->server_type == SILC_ROUTER ?
2284 TRUE : FALSE, channel,
2285 sender->id, SILC_ID_CLIENT_LEN,
2288 /* Send command reply */
2289 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2290 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2291 SILC_STATUS_OK, ident, 2,
2293 3, channel->invite_list,
2294 channel->invite_list ?
2295 strlen(channel->invite_list) :
2297 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2298 packet->data, packet->len, FALSE);
2299 silc_buffer_free(packet);
2305 silc_free(channel_id);
2306 silc_server_command_free(cmd);
2311 SilcSocketConnection sock;
2315 /* Quits connection to client. This gets called if client won't
2316 close the connection even when it has issued QUIT command. */
2318 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2320 QuitInternal q = (QuitInternal)context;
2322 /* Free all client specific data, such as client entry and entires
2323 on channels this client may be on. */
2324 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2326 q->sock->user_data = NULL;
2328 /* Close the connection on our side */
2329 silc_server_close_connection(q->server, q->sock);
2331 silc_free(q->signoff);
2335 /* Quits SILC session. This is the normal way to disconnect client. */
2337 SILC_SERVER_CMD_FUNC(quit)
2339 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2340 SilcServer server = cmd->server;
2341 SilcSocketConnection sock = cmd->sock;
2343 unsigned char *tmp = NULL;
2344 unsigned int len = 0;
2346 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2348 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2351 /* Get destination ID */
2352 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2356 q = silc_calloc(1, sizeof(*q));
2359 q->signoff = tmp ? strdup(tmp) : NULL;
2361 /* We quit the connection with little timeout */
2362 silc_task_register(server->timeout_queue, sock->sock,
2363 silc_server_command_quit_cb, (void *)q,
2364 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2367 silc_server_command_free(cmd);
2370 /* Server side of command KILL. This command is used by router operator
2371 to remove an client from the SILC Network temporarily. */
2373 SILC_SERVER_CMD_FUNC(kill)
2375 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2376 SilcServer server = cmd->server;
2377 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2378 SilcClientEntry remote_client;
2379 SilcClientID *client_id;
2380 unsigned char *tmp, *comment;
2381 unsigned int tmp_len, tmp_len2;
2383 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2385 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2388 /* KILL command works only on router */
2389 if (server->server_type != SILC_ROUTER) {
2390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2391 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2395 /* Check whether client has the permissions. */
2396 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2398 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2402 /* Get the client ID */
2403 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2406 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2409 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2411 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2412 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2416 /* Get the client entry */
2417 remote_client = silc_idlist_find_client_by_id(server->local_list,
2419 if (!remote_client) {
2420 remote_client = silc_idlist_find_client_by_id(server->global_list,
2422 if (!remote_client) {
2423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2424 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2430 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2434 /* Send reply to the sender */
2435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2438 /* Send the KILL notify packets. First send it to the channel, then
2439 to our primary router and then directly to the client who is being
2440 killed right now. */
2442 /* Send KILLED notify to the channels. It is not sent to the client
2443 as it will be sent differently destined directly to the client and not
2445 silc_server_send_notify_on_channels(server, remote_client,
2446 remote_client, SILC_NOTIFY_TYPE_KILLED,
2449 comment, comment ? tmp_len2 : 0);
2451 /* Send KILLED notify to primary route */
2452 if (!server->standalone)
2453 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2454 remote_client->id, SILC_ID_CLIENT_LEN,
2457 /* Send KILLED notify to the client directly */
2458 silc_server_send_notify_killed(server, remote_client->connection ?
2459 remote_client->connection :
2460 remote_client->router->connection, FALSE,
2461 remote_client->id, SILC_ID_CLIENT_LEN,
2464 /* Remove the client from all channels. This generates new keys to the
2465 channels as well. */
2466 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2469 /* Remove the client entry, If it is locally connected then we will also
2470 disconnect the client here */
2471 if (remote_client->data.registered && remote_client->connection) {
2472 /* Remove locally conneted client */
2473 SilcSocketConnection sock = remote_client->connection;
2474 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2475 silc_server_close_connection(server, sock);
2477 /* Remove remote client */
2478 if (!silc_idlist_del_client(server->global_list, remote_client))
2479 silc_idlist_del_client(server->local_list, remote_client);
2483 silc_server_command_free(cmd);
2486 /* Server side of command INFO. This sends information about us to
2487 the client. If client requested specific server we will send the
2488 command to that server. */
2490 SILC_SERVER_CMD_FUNC(info)
2492 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2493 SilcServer server = cmd->server;
2494 SilcBuffer packet, idp;
2495 char *dest_server, *server_info = NULL, *server_name;
2496 unsigned short ident = silc_command_get_ident(cmd->payload);
2497 SilcServerEntry entry = NULL;
2499 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
2501 /* Get server name */
2502 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2505 SILC_STATUS_ERR_NO_SUCH_SERVER);
2509 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2510 /* Send our reply */
2511 char info_string[256];
2513 memset(info_string, 0, sizeof(info_string));
2514 snprintf(info_string, sizeof(info_string),
2515 "location: %s server: %s admin: %s <%s>",
2516 server->config->admin_info->location,
2517 server->config->admin_info->server_type,
2518 server->config->admin_info->admin_name,
2519 server->config->admin_info->admin_email);
2521 server_info = info_string;
2522 entry = server->id_entry;
2524 /* Check whether we have this server cached */
2525 entry = silc_idlist_find_server_by_name(server->global_list,
2528 entry = silc_idlist_find_server_by_name(server->local_list,
2532 if (server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2533 /* Send to the server */
2535 unsigned short old_ident;
2537 old_ident = silc_command_get_ident(cmd->payload);
2538 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2539 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2541 silc_server_packet_send(server, entry->connection,
2542 SILC_PACKET_COMMAND, cmd->packet->flags,
2543 tmpbuf->data, tmpbuf->len, TRUE);
2545 /* Reprocess this packet after received reply from router */
2546 silc_server_command_pending(server, SILC_COMMAND_INFO,
2547 silc_command_get_ident(cmd->payload),
2548 silc_server_command_destructor,
2549 silc_server_command_info,
2550 silc_server_command_dup(cmd));
2551 cmd->pending = TRUE;
2552 silc_command_set_ident(cmd->payload, old_ident);
2553 silc_buffer_free(tmpbuf);
2557 if (!entry && !cmd->pending && !server->standalone) {
2558 /* Send to the primary router */
2560 unsigned short old_ident;
2562 old_ident = silc_command_get_ident(cmd->payload);
2563 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2564 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2566 silc_server_packet_send(server, server->router->connection,
2567 SILC_PACKET_COMMAND, cmd->packet->flags,
2568 tmpbuf->data, tmpbuf->len, TRUE);
2570 /* Reprocess this packet after received reply from router */
2571 silc_server_command_pending(server, SILC_COMMAND_INFO,
2572 silc_command_get_ident(cmd->payload),
2573 silc_server_command_destructor,
2574 silc_server_command_info,
2575 silc_server_command_dup(cmd));
2576 cmd->pending = TRUE;
2577 silc_command_set_ident(cmd->payload, old_ident);
2578 silc_buffer_free(tmpbuf);
2584 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2585 SILC_STATUS_ERR_NO_SUCH_SERVER);
2589 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2591 server_info = entry->server_info;
2592 server_name = dest_server;
2594 /* Send the reply */
2595 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2596 SILC_STATUS_OK, ident, 3,
2597 2, idp->data, idp->len,
2599 strlen(server_name),
2601 strlen(server_info));
2602 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2603 packet->data, packet->len, FALSE);
2605 silc_buffer_free(packet);
2606 silc_buffer_free(idp);
2609 silc_server_command_free(cmd);
2612 /* Server side of command PING. This just replies to the ping. */
2614 SILC_SERVER_CMD_FUNC(ping)
2616 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2617 SilcServer server = cmd->server;
2622 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2625 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2627 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2628 SILC_STATUS_ERR_NO_SERVER_ID);
2631 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2635 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2636 /* Send our reply */
2637 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2640 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2641 SILC_STATUS_ERR_NO_SUCH_SERVER);
2648 silc_server_command_free(cmd);
2651 /* Internal routine to join channel. The channel sent to this function
2652 has been either created or resolved from ID lists. This joins the sent
2653 client to the channel. */
2655 static void silc_server_command_join_channel(SilcServer server,
2656 SilcServerCommandContext cmd,
2657 SilcChannelEntry channel,
2658 SilcClientID *client_id,
2662 SilcSocketConnection sock = cmd->sock;
2664 unsigned int tmp_len, user_count;
2665 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2666 SilcClientEntry client;
2667 SilcChannelClientEntry chl;
2668 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2669 unsigned short ident = silc_command_get_ident(cmd->payload);
2672 SILC_LOG_DEBUG(("Start"));
2677 /* Get the client entry */
2678 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2679 client = (SilcClientEntry)sock->user_data;
2681 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2688 * Check channel modes
2691 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2692 strncat(check, client->nickname, strlen(client->nickname));
2693 if (!strchr(client->nickname, '@')) {
2694 strncat(check, "@", 1);
2695 strncat(check, server->server_name, strlen(server->server_name));
2697 strncat(check, "!", 1);
2698 strncat(check, client->username, strlen(client->username));
2699 if (!strchr(client->username, '@')) {
2700 strncat(check, "@", 1);
2701 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2705 /* Check invite list if channel is invite-only channel */
2706 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
2707 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2708 if (!channel->invite_list) {
2709 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2710 SILC_STATUS_ERR_NOT_INVITED);
2714 if (!silc_string_match(channel->invite_list, check)) {
2715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2716 SILC_STATUS_ERR_NOT_INVITED);
2721 /* Check ban list if it exists. If the client's nickname, server,
2722 username and/or hostname is in the ban list the access to the
2723 channel is denied. */
2724 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2725 if (silc_string_match(channel->ban_list, check)) {
2726 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2727 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2732 /* Get passphrase */
2733 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2735 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2736 memcpy(passphrase, tmp, tmp_len);
2739 /* Check the channel passphrase if set. */
2740 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2741 if (!passphrase || memcmp(channel->passphrase, passphrase,
2742 strlen(channel->passphrase))) {
2743 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2744 SILC_STATUS_ERR_BAD_PASSWORD);
2749 /* Check user count limit if set. */
2750 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2751 if (silc_list_count(channel->user_list) + 1 >
2752 channel->user_limit) {
2753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2754 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2760 * Client is allowed to join to the channel. Make it happen.
2763 /* Check whether the client already is on the channel */
2764 if (silc_server_client_on_channel(client, channel)) {
2765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2766 SILC_STATUS_ERR_USER_ON_CHANNEL);
2770 /* Generate new channel key as protocol dictates */
2771 if ((!created && silc_list_count(channel->user_list) > 0) ||
2772 !channel->channel_key)
2773 silc_server_create_channel_key(server, channel, 0);
2775 /* Send the channel key. This is broadcasted to the channel but is not
2776 sent to the client who is joining to the channel. */
2777 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2778 silc_server_send_channel_key(server, NULL, channel,
2779 server->server_type == SILC_ROUTER ?
2780 FALSE : !server->standalone);
2782 /* Join the client to the channel by adding it to channel's user list.
2783 Add also the channel to client entry's channels list for fast cross-
2785 chl = silc_calloc(1, sizeof(*chl));
2787 chl->client = client;
2788 chl->channel = channel;
2789 silc_list_add(channel->user_list, chl);
2790 silc_list_add(client->channels, chl);
2792 /* Get users on the channel */
2793 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2796 /* Encode Client ID Payload of the original client who wants to join */
2797 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2799 /* Encode command reply packet */
2800 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2801 SILC_PUT32_MSB(channel->mode, mode);
2802 SILC_PUT32_MSB(created, tmp2);
2803 SILC_PUT32_MSB(user_count, tmp3);
2805 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2806 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2807 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2808 strlen(channel->channel_key->
2810 channel->channel_key->cipher->name,
2811 channel->key_len / 8, channel->key);
2816 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2817 SILC_STATUS_OK, ident, 13,
2818 2, channel->channel_name,
2819 strlen(channel->channel_name),
2820 3, chidp->data, chidp->len,
2821 4, clidp->data, clidp->len,
2824 7, keyp ? keyp->data : NULL,
2825 keyp ? keyp->len : 0,
2826 8, channel->ban_list,
2828 strlen(channel->ban_list) : 0,
2829 9, channel->invite_list,
2830 channel->invite_list ?
2831 strlen(channel->invite_list) : 0,
2834 strlen(channel->topic) : 0,
2835 11, channel->hmac->hmac->name,
2836 strlen(channel->hmac->hmac->name),
2838 13, user_list->data, user_list->len,
2839 14, mode_list->data,
2842 /* Send command reply */
2843 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2844 reply->data, reply->len, FALSE);
2846 if (!cmd->pending) {
2847 /* Send JOIN notify to locally connected clients on the channel */
2848 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2849 SILC_NOTIFY_TYPE_JOIN, 2,
2850 clidp->data, clidp->len,
2851 chidp->data, chidp->len);
2853 /* Send JOIN notify packet to our primary router */
2854 if (!server->standalone)
2855 silc_server_send_notify_join(server, server->router->connection,
2856 server->server_type == SILC_ROUTER ?
2857 TRUE : FALSE, channel, client->id,
2858 SILC_ID_CLIENT_LEN);
2861 silc_buffer_free(reply);
2862 silc_buffer_free(clidp);
2863 silc_buffer_free(chidp);
2864 silc_buffer_free(keyp);
2865 silc_buffer_free(user_list);
2866 silc_buffer_free(mode_list);
2870 silc_free(passphrase);
2873 /* Server side of command JOIN. Joins client into requested channel. If
2874 the channel does not exist it will be created. */
2876 SILC_SERVER_CMD_FUNC(join)
2878 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2879 SilcServer server = cmd->server;
2881 char *tmp, *channel_name = NULL, *cipher, *hmac;
2882 SilcChannelEntry channel;
2883 unsigned int umode = 0;
2884 int created = FALSE;
2885 SilcClientID *client_id;
2887 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2889 /* Get channel name */
2890 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2892 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2893 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2898 if (strlen(channel_name) > 256)
2899 channel_name[255] = '\0';
2901 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2902 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2903 SILC_STATUS_ERR_BAD_CHANNEL);
2904 silc_free(channel_name);
2908 /* Get Client ID of the client who is joining to the channel */
2909 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2912 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2915 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2917 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2918 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2922 /* Get cipher and hmac name */
2923 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2924 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2926 /* See if the channel exists */
2927 channel = silc_idlist_find_channel_by_name(server->local_list,
2928 channel_name, NULL);
2930 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2931 /* If this is coming from client the Client ID in the command packet must
2932 be same as the client's ID. */
2933 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2934 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2935 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2936 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2937 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2943 /* Channel not found */
2945 /* If we are standalone server we don't have a router, we just create
2946 the channel by ourselves. */
2947 if (server->standalone) {
2948 channel = silc_server_create_new_channel(server, server->id, cipher,
2949 hmac, channel_name, TRUE);
2951 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2952 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2956 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2961 /* The channel does not exist on our server. If we are normal server
2962 we will send JOIN command to our router which will handle the
2963 joining procedure (either creates the channel if it doesn't exist
2964 or joins the client to it). */
2965 if (server->server_type == SILC_SERVER) {
2967 unsigned short old_ident;
2969 old_ident = silc_command_get_ident(cmd->payload);
2970 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2971 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2973 /* Send JOIN command to our router */
2974 silc_server_packet_send(server, (SilcSocketConnection)
2975 server->router->connection,
2976 SILC_PACKET_COMMAND, cmd->packet->flags,
2977 tmpbuf->data, tmpbuf->len, TRUE);
2979 /* Reprocess this packet after received reply from router */
2980 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2981 silc_command_get_ident(cmd->payload),
2982 silc_server_command_destructor,
2983 silc_server_command_join,
2984 silc_server_command_dup(cmd));
2985 cmd->pending = TRUE;
2989 /* We are router and the channel does not seem exist so we will check
2990 our global list as well for the channel. */
2991 channel = silc_idlist_find_channel_by_name(server->global_list,
2992 channel_name, NULL);
2994 /* Channel really does not exist, create it */
2995 channel = silc_server_create_new_channel(server, server->id, cipher,
2996 hmac, channel_name, TRUE);
2998 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2999 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3003 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3010 /* Channel not found */
3012 /* If the command came from router and/or we are normal server then
3013 something went wrong with the joining as the channel was not found.
3014 We can't do anything else but ignore this. */
3015 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3016 server->server_type == SILC_SERVER)
3019 /* We are router and the channel does not seem exist so we will check
3020 our global list as well for the channel. */
3021 channel = silc_idlist_find_channel_by_name(server->global_list,
3022 channel_name, NULL);
3024 /* Channel really does not exist, create it */
3025 channel = silc_server_create_new_channel(server, server->id, cipher,
3026 hmac, channel_name, TRUE);
3028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3029 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3033 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3039 /* If the channel does not have global users and is also empty it means the
3040 channel was created globally (by our router) and the client will be the
3041 channel founder and operator. */
3042 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3043 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3044 created = TRUE; /* Created globally by our router */
3047 /* Join to the channel */
3048 silc_server_command_join_channel(server, cmd, channel, client_id,
3051 silc_free(client_id);
3054 silc_server_command_free(cmd);
3057 /* Server side of command MOTD. Sends server's current "message of the
3058 day" to the client. */
3060 SILC_SERVER_CMD_FUNC(motd)
3062 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3063 SilcServer server = cmd->server;
3064 SilcBuffer packet, idp;
3065 char *motd, *dest_server;
3067 unsigned short ident = silc_command_get_ident(cmd->payload);
3069 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3071 /* Get server name */
3072 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3074 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3075 SILC_STATUS_ERR_NO_SUCH_SERVER);
3079 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3082 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3084 if (server->config && server->config->motd &&
3085 server->config->motd->motd_file) {
3087 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3092 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3093 SILC_STATUS_OK, ident, 2,
3099 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3100 SILC_STATUS_OK, ident, 1,
3104 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3105 packet->data, packet->len, FALSE);
3106 silc_buffer_free(packet);
3107 silc_buffer_free(idp);
3109 SilcServerEntry entry;
3111 /* Check whether we have this server cached */
3112 entry = silc_idlist_find_server_by_name(server->global_list,
3115 entry = silc_idlist_find_server_by_name(server->local_list,
3119 if (server->server_type == SILC_ROUTER && !cmd->pending &&
3120 entry && !entry->motd) {
3121 /* Send to the server */
3123 unsigned short old_ident;
3125 old_ident = silc_command_get_ident(cmd->payload);
3126 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3127 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3129 silc_server_packet_send(server, entry->connection,
3130 SILC_PACKET_COMMAND, cmd->packet->flags,
3131 tmpbuf->data, tmpbuf->len, TRUE);
3133 /* Reprocess this packet after received reply from router */
3134 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3135 silc_command_get_ident(cmd->payload),
3136 silc_server_command_destructor,
3137 silc_server_command_motd,
3138 silc_server_command_dup(cmd));
3139 cmd->pending = TRUE;
3140 silc_command_set_ident(cmd->payload, old_ident);
3141 silc_buffer_free(tmpbuf);
3145 if (!entry && !cmd->pending && !server->standalone) {
3146 /* Send to the primary router */
3148 unsigned short old_ident;
3150 old_ident = silc_command_get_ident(cmd->payload);
3151 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3152 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3154 silc_server_packet_send(server, server->router->connection,
3155 SILC_PACKET_COMMAND, cmd->packet->flags,
3156 tmpbuf->data, tmpbuf->len, TRUE);
3158 /* Reprocess this packet after received reply from router */
3159 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3160 silc_command_get_ident(cmd->payload),
3161 silc_server_command_destructor,
3162 silc_server_command_motd,
3163 silc_server_command_dup(cmd));
3164 cmd->pending = TRUE;
3165 silc_command_set_ident(cmd->payload, old_ident);
3166 silc_buffer_free(tmpbuf);
3171 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3172 SILC_STATUS_ERR_NO_SUCH_SERVER);
3176 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3179 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3180 SILC_STATUS_OK, ident, 2,
3183 strlen(entry->motd));
3185 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3186 SILC_STATUS_OK, ident, 1,
3189 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3190 packet->data, packet->len, FALSE);
3191 silc_buffer_free(packet);
3192 silc_buffer_free(idp);
3196 silc_server_command_free(cmd);
3199 /* Server side of command UMODE. Client can use this command to set/unset
3200 user mode. Client actually cannot set itself to be as server/router
3201 operator so this can be used only to unset the modes. */
3203 SILC_SERVER_CMD_FUNC(umode)
3205 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3206 SilcServer server = cmd->server;
3207 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3209 unsigned char *tmp_mask;
3211 unsigned short ident = silc_command_get_ident(cmd->payload);
3213 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3216 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3218 /* Get the client's mode mask */
3219 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3221 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3222 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3225 SILC_GET32_MSB(mask, tmp_mask);
3231 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3232 /* Cannot operator mode */
3233 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3234 SILC_STATUS_ERR_PERM_DENIED);
3237 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3238 /* Remove the server operator rights */
3239 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3242 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3243 /* Cannot operator mode */
3244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3245 SILC_STATUS_ERR_PERM_DENIED);
3248 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3249 /* Remove the router operator rights */
3250 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3253 /* Send UMODE change to primary router */
3254 if (!server->standalone)
3255 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3256 client->id, SILC_ID_CLIENT_LEN,
3259 /* Send command reply to sender */
3260 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3261 SILC_STATUS_OK, ident, 1,
3263 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3264 packet->data, packet->len, FALSE);
3265 silc_buffer_free(packet);
3268 silc_server_command_free(cmd);
3271 /* Checks that client has rights to add or remove channel modes. If any
3272 of the checks fails FALSE is returned. */
3274 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3275 SilcChannelClientEntry client,
3278 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3279 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3281 /* Check whether has rights to change anything */
3282 if (!is_op && !is_fo)
3285 /* Check whether has rights to change everything */
3289 /* We know that client is channel operator, check that they are not
3290 changing anything that requires channel founder rights. Rest of the
3291 modes are available automatically for channel operator. */
3293 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3294 if (is_op && !is_fo)
3297 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3298 if (is_op && !is_fo)
3303 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3304 if (is_op && !is_fo)
3307 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3308 if (is_op && !is_fo)
3313 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3314 if (is_op && !is_fo)
3317 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3318 if (is_op && !is_fo)
3326 /* Server side command of CMODE. Changes channel mode */
3328 SILC_SERVER_CMD_FUNC(cmode)
3330 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3331 SilcServer server = cmd->server;
3332 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3333 SilcChannelID *channel_id;
3334 SilcChannelEntry channel;
3335 SilcChannelClientEntry chl;
3336 SilcBuffer packet, cidp;
3337 unsigned char *tmp, *tmp_id, *tmp_mask;
3338 char *cipher = NULL, *hmac = NULL;
3339 unsigned int argc, mode_mask, tmp_len, tmp_len2;
3340 unsigned short ident = silc_command_get_ident(cmd->payload);
3342 SILC_LOG_DEBUG(("Start"));
3344 argc = silc_argument_get_arg_num(cmd->args);
3346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3347 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3351 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3352 SILC_STATUS_ERR_TOO_MANY_PARAMS);
3356 /* Get Channel ID */
3357 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3360 SILC_STATUS_ERR_NO_CHANNEL_ID);
3363 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3365 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3366 SILC_STATUS_ERR_NO_CHANNEL_ID);
3370 /* Get the channel mode mask */
3371 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3374 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3377 SILC_GET32_MSB(mode_mask, tmp_mask);
3379 /* Get channel entry */
3380 channel = silc_idlist_find_channel_by_id(server->local_list,
3383 channel = silc_idlist_find_channel_by_id(server->global_list,
3386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3387 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3392 /* Check whether this client is on the channel */
3393 if (!silc_server_client_on_channel(client, channel)) {
3394 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3395 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3399 /* Get entry to the channel user list */
3400 silc_list_start(channel->user_list);
3401 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3402 if (chl->client == client)
3405 /* Check that client has rights to change any requested channel modes */
3406 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3408 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3413 * Check the modes. Modes that requires nothing special operation are
3417 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3418 /* Channel uses private keys to protect traffic. Client(s) has set the
3419 key locally they want to use, server does not know that key. */
3420 /* Nothing interesting to do here */
3422 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3423 /* The mode is removed and we need to generate and distribute
3424 new channel key. Clients are not using private channel keys
3425 anymore after this. */
3427 /* Re-generate channel key */
3428 silc_server_create_channel_key(server, channel, 0);
3430 /* Send the channel key. This sends it to our local clients and if
3431 we are normal server to our router as well. */
3432 silc_server_send_channel_key(server, NULL, channel,
3433 server->server_type == SILC_ROUTER ?
3434 FALSE : !server->standalone);
3436 cipher = channel->channel_key->cipher->name;
3437 hmac = channel->hmac->hmac->name;
3441 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3442 /* User limit is set on channel */
3443 unsigned int user_limit;
3445 /* Get user limit */
3446 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3448 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3449 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3450 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3454 SILC_GET32_MSB(user_limit, tmp);
3455 channel->user_limit = user_limit;
3458 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3459 /* User limit mode is unset. Remove user limit */
3460 channel->user_limit = 0;
3463 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3464 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3465 /* Passphrase has been set to channel */
3467 /* Get the passphrase */
3468 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3470 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3471 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3475 /* Save the passphrase */
3476 channel->passphrase = strdup(tmp);
3479 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3480 /* Passphrase mode is unset. remove the passphrase */
3481 if (channel->passphrase) {
3482 silc_free(channel->passphrase);
3483 channel->passphrase = NULL;
3488 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3489 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3490 /* Cipher to use protect the traffic */
3493 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3496 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3500 /* Delete old cipher and allocate the new one */
3501 silc_cipher_free(channel->channel_key);
3502 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3503 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3504 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3508 /* Re-generate channel key */
3509 silc_server_create_channel_key(server, channel, 0);
3511 /* Send the channel key. This sends it to our local clients and if
3512 we are normal server to our router as well. */
3513 silc_server_send_channel_key(server, NULL, channel,
3514 server->server_type == SILC_ROUTER ?
3515 FALSE : !server->standalone);
3518 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3519 /* Cipher mode is unset. Remove the cipher and revert back to
3521 cipher = channel->cipher;
3523 /* Delete old cipher and allocate default one */
3524 silc_cipher_free(channel->channel_key);
3525 if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc",
3526 &channel->channel_key)) {
3527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3528 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3532 /* Re-generate channel key */
3533 silc_server_create_channel_key(server, channel, 0);
3535 /* Send the channel key. This sends it to our local clients and if
3536 we are normal server to our router as well. */
3537 silc_server_send_channel_key(server, NULL, channel,
3538 server->server_type == SILC_ROUTER ?
3539 FALSE : !server->standalone);
3543 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3544 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3545 /* HMAC to use protect the traffic */
3546 unsigned char hash[32];
3549 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3552 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3556 /* Delete old hmac and allocate the new one */
3557 silc_hmac_free(channel->hmac);
3558 if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3560 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3564 /* Set the HMAC key out of current channel key. The client must do
3566 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3568 silc_hmac_set_key(channel->hmac, hash,
3569 silc_hash_len(channel->hmac->hash));
3570 memset(hash, 0, sizeof(hash));
3573 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3574 /* Hmac mode is unset. Remove the hmac and revert back to
3576 unsigned char hash[32];
3577 hmac = channel->hmac_name;
3579 /* Delete old hmac and allocate default one */
3580 silc_hmac_free(channel->hmac);
3581 if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL,
3583 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3584 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3588 /* Set the HMAC key out of current channel key. The client must do
3590 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3592 silc_hmac_set_key(channel->hmac, hash,
3593 silc_hash_len(channel->hmac->hash));
3594 memset(hash, 0, sizeof(hash));
3598 /* Finally, set the mode */
3599 channel->mode = mode_mask;
3601 /* Send CMODE_CHANGE notify */
3602 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3603 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3604 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3605 cidp->data, cidp->len,
3607 cipher, cipher ? strlen(cipher) : 0,
3608 hmac, hmac ? strlen(hmac) : 0);
3610 /* Set CMODE notify type to network */
3611 if (!server->standalone)
3612 silc_server_send_notify_cmode(server, server->router->connection,
3613 server->server_type == SILC_ROUTER ?
3614 TRUE : FALSE, channel,
3615 mode_mask, client->id, SILC_ID_CLIENT_LEN,
3618 /* Send command reply to sender */
3619 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3620 SILC_STATUS_OK, ident, 1,
3622 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3623 packet->data, packet->len, FALSE);
3625 silc_buffer_free(packet);
3626 silc_free(channel_id);
3630 silc_server_command_free(cmd);
3633 /* Server side of CUMODE command. Changes client's mode on a channel. */
3635 SILC_SERVER_CMD_FUNC(cumode)
3637 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3638 SilcServer server = cmd->server;
3639 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3640 SilcChannelID *channel_id;
3641 SilcClientID *client_id;
3642 SilcChannelEntry channel;
3643 SilcClientEntry target_client;
3644 SilcChannelClientEntry chl;
3645 SilcBuffer packet, idp;
3646 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3647 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3649 unsigned short ident = silc_command_get_ident(cmd->payload);
3651 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3653 /* Get Channel ID */
3654 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3656 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3657 SILC_STATUS_ERR_NO_CHANNEL_ID);
3660 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3662 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3663 SILC_STATUS_ERR_NO_CHANNEL_ID);
3667 /* Get channel entry */
3668 channel = silc_idlist_find_channel_by_id(server->local_list,
3671 channel = silc_idlist_find_channel_by_id(server->global_list,
3674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3675 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3680 /* Check whether sender is on the channel */
3681 if (!silc_server_client_on_channel(client, channel)) {
3682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3683 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3687 /* Check that client has rights to change other's rights */
3688 silc_list_start(channel->user_list);
3689 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3690 if (chl->client == client) {
3691 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3692 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3693 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3694 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3698 sender_mask = chl->mode;
3703 /* Get the target client's channel mode mask */
3704 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3707 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3710 SILC_GET32_MSB(target_mask, tmp_mask);
3712 /* Get target Client ID */
3713 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3716 SILC_STATUS_ERR_NO_CLIENT_ID);
3719 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3721 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3722 SILC_STATUS_ERR_NO_CLIENT_ID);
3726 /* Get target client's entry */
3727 target_client = silc_idlist_find_client_by_id(server->local_list,
3729 if (!target_client) {
3730 target_client = silc_idlist_find_client_by_id(server->global_list,
3734 /* Check whether target client is on the channel */
3735 if (!silc_server_client_on_channel(target_client, channel)) {
3736 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3737 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3741 /* Get entry to the channel user list */
3742 silc_list_start(channel->user_list);
3743 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3744 if (chl->client == target_client)
3751 /* If the target client is founder, no one else can change their mode
3753 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3754 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3755 SILC_STATUS_ERR_NOT_YOU);
3759 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3760 /* Cannot promote anyone to channel founder */
3761 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3762 SILC_STATUS_ERR_NOT_YOU);
3765 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3766 if (target_client == client) {
3767 /* Remove channel founder rights from itself */
3768 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3771 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3772 SILC_STATUS_ERR_NOT_YOU);
3778 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3779 /* Promote to operator */
3780 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3781 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3785 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3786 /* Demote to normal user */
3787 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3792 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3794 /* Send notify to channel, notify only if mode was actually changed. */
3796 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3797 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3798 idp->data, idp->len,
3802 /* Set CUMODE notify type to network */
3803 if (!server->standalone)
3804 silc_server_send_notify_cumode(server, server->router->connection,
3805 server->server_type == SILC_ROUTER ?
3806 TRUE : FALSE, channel,
3807 target_mask, client->id,
3810 SILC_ID_CLIENT_LEN);
3813 /* Send command reply to sender */
3814 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3815 SILC_STATUS_OK, ident, 2,
3817 3, tmp_id, tmp_len);
3818 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3819 packet->data, packet->len, FALSE);
3821 silc_buffer_free(packet);
3822 silc_free(channel_id);
3823 silc_free(client_id);
3824 silc_buffer_free(idp);
3827 silc_server_command_free(cmd);
3830 /* Server side of KICK command. Kicks client out of channel. */
3832 SILC_SERVER_CMD_FUNC(kick)
3834 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3835 SilcServer server = cmd->server;
3836 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3837 SilcClientEntry target_client;
3838 SilcChannelID *channel_id;
3839 SilcClientID *client_id;
3840 SilcChannelEntry channel;
3841 SilcChannelClientEntry chl;
3843 unsigned int tmp_len;
3844 unsigned char *tmp, *comment;
3846 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3848 /* Get Channel ID */
3849 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3851 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3852 SILC_STATUS_ERR_NO_CHANNEL_ID);
3855 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3857 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3858 SILC_STATUS_ERR_NO_CHANNEL_ID);
3862 /* Get channel entry */
3863 channel = silc_idlist_find_channel_by_id(server->local_list,
3866 channel = silc_idlist_find_channel_by_id(server->local_list,
3869 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3870 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3875 /* Check whether sender is on the channel */
3876 if (!silc_server_client_on_channel(client, channel)) {
3877 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3878 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3882 /* Check that the kicker is channel operator or channel founder */
3883 silc_list_start(channel->user_list);
3884 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3885 if (chl->client == client) {
3886 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3887 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3888 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3895 /* Get target Client ID */
3896 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3898 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3899 SILC_STATUS_ERR_NO_CLIENT_ID);
3902 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3905 SILC_STATUS_ERR_NO_CLIENT_ID);
3909 /* Get target client's entry */
3910 target_client = silc_idlist_find_client_by_id(server->local_list,
3912 if (!target_client) {
3913 target_client = silc_idlist_find_client_by_id(server->global_list,
3917 /* Check that the target client is not channel founder. Channel founder
3918 cannot be kicked from the channel. */
3919 silc_list_start(channel->user_list);
3920 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3921 if (chl->client == target_client) {
3922 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3924 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3931 /* Check whether target client is on the channel */
3932 if (!silc_server_client_on_channel(target_client, channel)) {
3933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3934 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3940 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3944 /* Send command reply to sender */
3945 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3948 /* Send KICKED notify to local clients on the channel */
3949 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3950 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3951 SILC_NOTIFY_TYPE_KICKED,
3953 idp->data, idp->len,
3954 comment, comment ? strlen(comment) : 0);
3955 silc_buffer_free(idp);
3957 /* Remove the client from the channel. If the channel does not exist
3958 after removing the client then the client kicked itself off the channel
3959 and we don't have to send anything after that. */
3960 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3961 target_client, FALSE))
3964 /* Send KICKED notify to primary route */
3965 if (!server->standalone)
3966 silc_server_send_notify_kicked(server, server->router->connection,
3967 server->server_type == SILC_ROUTER ?
3968 TRUE : FALSE, channel,
3969 target_client->id, SILC_ID_CLIENT_LEN,
3972 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3973 /* Re-generate channel key */
3974 silc_server_create_channel_key(server, channel, 0);
3976 /* Send the channel key to the channel. The key of course is not sent
3977 to the client who was kicked off the channel. */
3978 silc_server_send_channel_key(server, target_client->connection, channel,
3979 server->server_type == SILC_ROUTER ?
3980 FALSE : !server->standalone);
3984 silc_server_command_free(cmd);
3987 /* Server side of OPER command. Client uses this comand to obtain server
3988 operator privileges to this server/router. */
3990 SILC_SERVER_CMD_FUNC(oper)
3992 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3993 SilcServer server = cmd->server;
3994 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3995 unsigned char *username, *auth;
3996 unsigned int tmp_len;
3997 SilcServerConfigSectionAdminConnection *admin;
3998 SilcIDListData idata = (SilcIDListData)client;
4000 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
4002 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4005 /* Get the username */
4006 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4008 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4009 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4013 /* Get the admin configuration */
4014 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4015 username, client->nickname);
4017 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4018 username, client->nickname);
4020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4021 SILC_STATUS_ERR_AUTH_FAILED);
4026 /* Get the authentication payload */
4027 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4030 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4034 /* Verify the authentication data */
4035 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4036 admin->auth_data, admin->auth_data_len,
4037 idata->hash, client->id, SILC_ID_CLIENT)) {
4038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4039 SILC_STATUS_ERR_AUTH_FAILED);
4043 /* Client is now server operator */
4044 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4046 /* Send UMODE change to primary router */
4047 if (!server->standalone)
4048 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4049 client->id, SILC_ID_CLIENT_LEN,
4052 /* Send reply to the sender */
4053 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4057 silc_server_command_free(cmd);
4060 /* Server side of SILCOPER command. Client uses this comand to obtain router
4061 operator privileges to this router. */
4063 SILC_SERVER_CMD_FUNC(silcoper)
4065 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4066 SilcServer server = cmd->server;
4067 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4068 unsigned char *username, *auth;
4069 unsigned int tmp_len;
4070 SilcServerConfigSectionAdminConnection *admin;
4071 SilcIDListData idata = (SilcIDListData)client;
4073 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4075 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4078 /* Get the username */
4079 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4082 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4086 /* Get the admin configuration */
4087 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4088 username, client->nickname);
4090 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4091 username, client->nickname);
4093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4094 SILC_STATUS_ERR_AUTH_FAILED);
4099 /* Get the authentication payload */
4100 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4102 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4103 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4107 /* Verify the authentication data */
4108 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4109 admin->auth_data, admin->auth_data_len,
4110 idata->hash, client->id, SILC_ID_CLIENT)) {
4111 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4112 SILC_STATUS_ERR_AUTH_FAILED);
4116 /* Client is now router operator */
4117 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4119 /* Send UMODE change to primary router */
4120 if (!server->standalone)
4121 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4122 client->id, SILC_ID_CLIENT_LEN,
4125 /* Send reply to the sender */
4126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4130 silc_server_command_free(cmd);
4133 /* Server side command of CONNECT. Connects us to the specified remote
4134 server or router. */
4136 SILC_SERVER_CMD_FUNC(connect)
4138 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4139 SilcServer server = cmd->server;
4140 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4141 unsigned char *tmp, *host;
4142 unsigned int tmp_len;
4143 unsigned int port = SILC_PORT;
4145 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4147 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4150 /* Check whether client has the permissions. */
4151 if (client->mode == SILC_UMODE_NONE) {
4152 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4153 SILC_STATUS_ERR_NO_SERVER_PRIV);
4157 if (server->server_type == SILC_ROUTER &&
4158 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4159 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4160 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4164 /* Get the remote server */
4165 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4168 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4173 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4175 SILC_GET32_MSB(port, tmp);
4177 /* Create the connection. It is done with timeout and is async. */
4178 silc_server_create_connection(server, host, port);
4180 /* Send reply to the sender */
4181 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4185 silc_server_command_free(cmd);
4188 SILC_SERVER_CMD_FUNC(restart)
4192 /* Server side command of CLOSE. Closes connection to a specified server. */
4194 SILC_SERVER_CMD_FUNC(close)
4196 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4197 SilcServer server = cmd->server;
4198 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4199 SilcServerEntry server_entry;
4200 SilcSocketConnection sock;
4202 unsigned int tmp_len;
4203 unsigned char *name;
4204 unsigned int port = SILC_PORT;
4206 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, 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_CLOSE,
4214 SILC_STATUS_ERR_NO_SERVER_PRIV);
4218 /* Get the remote server */
4219 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4221 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4222 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4227 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4229 SILC_GET32_MSB(port, tmp);
4231 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4233 if (!server_entry) {
4234 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4235 SILC_STATUS_ERR_NO_SERVER_ID);
4239 /* Send reply to the sender */
4240 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4243 /* Close the connection to the server */
4244 sock = (SilcSocketConnection)server_entry->connection;
4245 silc_server_free_sock_user_data(server, sock);
4246 silc_server_close_connection(server, sock);
4249 silc_server_command_free(cmd);
4252 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4253 active connections. */
4255 SILC_SERVER_CMD_FUNC(shutdown)
4257 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4258 SilcServer server = cmd->server;
4259 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4261 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4263 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4266 /* Check whether client has the permission. */
4267 if (client->mode == SILC_UMODE_NONE) {
4268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4269 SILC_STATUS_ERR_NO_SERVER_PRIV);
4273 /* Send reply to the sender */
4274 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4277 /* Then, gracefully, or not, bring the server down. */
4278 silc_server_stop(server);
4282 silc_server_command_free(cmd);
4285 /* Server side command of LEAVE. Removes client from a channel. */
4287 SILC_SERVER_CMD_FUNC(leave)
4289 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4290 SilcServer server = cmd->server;
4291 SilcSocketConnection sock = cmd->sock;
4292 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4294 SilcChannelEntry channel;
4296 unsigned int i, len;
4299 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4301 /* Get Channel ID */
4302 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4305 SILC_STATUS_ERR_NO_CHANNEL_ID);
4308 id = silc_id_payload_parse_id(tmp, len);
4310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4311 SILC_STATUS_ERR_NO_CHANNEL_ID);
4315 /* Get channel entry */
4316 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4318 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4321 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4326 /* Check whether this client is on the channel */
4327 if (!silc_server_client_on_channel(id_entry, channel)) {
4328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4329 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4333 /* Notify routers that they should remove this client from their list
4334 of clients on the channel. Send LEAVE notify type. */
4335 if (!server->standalone)
4336 silc_server_send_notify_leave(server, server->router->connection,
4337 server->server_type == SILC_ROUTER ?
4338 TRUE : FALSE, channel, id_entry->id,
4339 SILC_ID_CLIENT_LEN);
4341 /* Remove client from channel */
4342 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4347 /* If the channel does not exist anymore we won't send anything */
4351 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4352 /* Re-generate channel key */
4353 silc_server_create_channel_key(server, channel, 0);
4355 /* Encode channel key payload to be distributed on the channel */
4357 silc_channel_key_payload_encode(len, tmp,
4358 strlen(channel->channel_key->
4360 channel->channel_key->cipher->name,
4361 channel->key_len / 8, channel->key);
4363 /* If we are normal server then we will send it to our router. If we
4364 are router we will send it to all local servers that has clients on
4366 if (server->server_type == SILC_SERVER) {
4367 if (!server->standalone)
4368 silc_server_packet_send(server,
4369 cmd->server->router->connection,
4370 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
4371 packet->len, FALSE);
4376 /* Send to locally connected clients on the channel */
4377 silc_server_packet_send_local_channel(server, channel,
4378 SILC_PACKET_CHANNEL_KEY, 0,
4379 packet->data, packet->len, FALSE);
4381 silc_buffer_free(packet);
4387 silc_server_command_free(cmd);
4390 /* Server side of command USERS. Resolves clients and their USERS currently
4391 joined on the requested channel. The list of Client ID's and their modes
4392 on the channel is sent back. */
4394 SILC_SERVER_CMD_FUNC(users)
4396 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4397 SilcServer server = cmd->server;
4398 SilcChannelEntry channel;
4401 unsigned char *channel_id;
4402 unsigned int channel_id_len;
4403 SilcBuffer client_id_list;
4404 SilcBuffer client_mode_list;
4405 unsigned char lc[4];
4406 unsigned int list_count = 0;
4407 unsigned short ident = silc_command_get_ident(cmd->payload);
4409 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4411 /* Get Channel ID */
4412 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4414 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4415 SILC_STATUS_ERR_NO_CHANNEL_ID);
4418 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4420 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4421 SILC_STATUS_ERR_NO_CHANNEL_ID);
4425 /* If we are server and we don't know about this channel we will send
4426 the command to our router. If we know about the channel then we also
4427 have the list of users already. */
4428 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4430 if (server->server_type == SILC_SERVER && !server->standalone &&
4434 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4435 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4437 /* Send USERS command */
4438 silc_server_packet_send(server, server->router->connection,
4439 SILC_PACKET_COMMAND, cmd->packet->flags,
4440 tmpbuf->data, tmpbuf->len, TRUE);
4442 /* Reprocess this packet after received reply */
4443 silc_server_command_pending(server, SILC_COMMAND_USERS,
4444 silc_command_get_ident(cmd->payload),
4445 silc_server_command_destructor,
4446 silc_server_command_users,
4447 silc_server_command_dup(cmd));
4448 cmd->pending = TRUE;
4449 silc_command_set_ident(cmd->payload, ident);
4451 silc_buffer_free(tmpbuf);
4456 /* We are router and we will check the global list as well. */
4457 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4459 /* Channel really does not exist */
4460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4461 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4466 /* Get the users list */
4467 silc_server_get_users_on_channel(server, channel, &client_id_list,
4468 &client_mode_list, &list_count);
4471 SILC_PUT32_MSB(list_count, lc);
4474 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4475 SILC_STATUS_OK, ident, 4,
4476 2, channel_id, channel_id_len,
4478 4, client_id_list->data,
4479 client_id_list->len,
4480 5, client_mode_list->data,
4481 client_mode_list->len);
4482 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4483 packet->data, packet->len, FALSE);
4485 silc_buffer_free(packet);
4486 silc_buffer_free(client_id_list);
4487 silc_buffer_free(client_mode_list);
4491 silc_server_command_free(cmd);
4494 /* Server side of command BAN. This is used to manage the ban list of the
4495 channel. To add clients and remove clients from the ban list. */
4497 SILC_SERVER_CMD_FUNC(ban)
4499 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4500 SilcServer server = cmd->server;
4501 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4503 SilcChannelEntry channel;
4504 SilcChannelClientEntry chl;
4505 SilcChannelID *channel_id = NULL;
4506 unsigned char *id, *add, *del;
4507 unsigned int id_len, tmp_len;
4508 unsigned short ident = silc_command_get_ident(cmd->payload);
4510 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4513 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4515 /* Get Channel ID */
4516 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4518 channel_id = silc_id_payload_parse_id(id, id_len);
4520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4521 SILC_STATUS_ERR_NO_CHANNEL_ID);
4526 /* Get channel entry. The server must know about the channel since the
4527 client is expected to be on the channel. */
4528 channel = silc_idlist_find_channel_by_id(server->local_list,
4531 channel = silc_idlist_find_channel_by_id(server->global_list,
4534 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4535 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4540 /* Check whether this client is on the channel */
4541 if (!silc_server_client_on_channel(client, channel)) {
4542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4543 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4547 /* Get entry to the channel user list */
4548 silc_list_start(channel->user_list);
4549 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4550 if (chl->client == client)
4553 /* The client must be at least channel operator. */
4554 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4555 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4556 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4560 /* Get the new ban and add it to the ban list */
4561 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4563 if (!channel->ban_list)
4564 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4566 channel->ban_list = silc_realloc(channel->ban_list,
4567 sizeof(*channel->ban_list) *
4569 strlen(channel->ban_list) + 2));
4570 if (add[tmp_len - 1] == ',')
4571 add[tmp_len - 1] = '\0';
4573 strncat(channel->ban_list, add, tmp_len);
4574 strncat(channel->ban_list, ",", 1);
4577 /* Get the ban to be removed and remove it from the list */
4578 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4579 if (del && channel->ban_list) {
4580 char *start, *end, *n;
4582 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4583 silc_free(channel->ban_list);
4584 channel->ban_list = NULL;
4586 start = strstr(channel->ban_list, del);
4587 if (start && strlen(start) >= tmp_len) {
4588 end = start + tmp_len;
4589 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4590 strncat(n, channel->ban_list, start - channel->ban_list);
4591 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4593 silc_free(channel->ban_list);
4594 channel->ban_list = n;
4599 /* Send the BAN notify type to our primary router. */
4600 if (!server->standalone && (add || del))
4601 silc_server_send_notify_ban(server, server->router->connection,
4602 server->server_type == SILC_ROUTER ?
4603 TRUE : FALSE, channel, add, del);
4605 /* Send the reply back to the client */
4606 if (channel->ban_list)
4608 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4609 SILC_STATUS_OK, ident, 2,
4611 3, channel->ban_list,
4612 strlen(channel->ban_list) - 1);
4615 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4616 SILC_STATUS_OK, ident, 1,
4619 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4620 packet->data, packet->len, FALSE);
4622 silc_buffer_free(packet);
4626 silc_free(channel_id);
4627 silc_server_command_free(cmd);