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);
1346 status = SILC_STATUS_OK;
1347 if (clients_count > 1)
1348 status = SILC_STATUS_LIST_START;
1350 for (i = 0; i < clients_count; i++) {
1353 if (entry->data.registered == FALSE) {
1354 if (clients_count == 1) {
1355 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1356 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1357 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1358 2, idp->data, idp->len);
1359 silc_buffer_free(idp);
1364 if (count && i - 1 == count)
1368 status = SILC_STATUS_LIST_ITEM;
1370 if (clients_count > 1 && i == clients_count - 1)
1371 status = SILC_STATUS_LIST_END;
1373 /* Send IDENTIFY reply */
1374 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1375 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1379 char nh[256], uh[256];
1380 SilcSocketConnection hsock;
1382 memset(uh, 0, sizeof(uh));
1383 memset(nh, 0, sizeof(nh));
1385 strncat(nh, entry->nickname, strlen(entry->nickname));
1386 if (!strchr(entry->nickname, '@')) {
1387 strncat(nh, "@", 1);
1388 len = entry->router ? strlen(entry->router->server_name) :
1389 strlen(server->server_name);
1390 strncat(nh, entry->router ? entry->router->server_name :
1391 server->server_name, len);
1394 if (!entry->username) {
1395 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1397 2, idp->data, idp->len,
1400 strncat(uh, entry->username, strlen(entry->username));
1401 if (!strchr(entry->username, '@')) {
1402 strncat(uh, "@", 1);
1403 hsock = (SilcSocketConnection)entry->connection;
1404 len = strlen(hsock->hostname);
1405 strncat(uh, hsock->hostname, len);
1408 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1410 2, idp->data, idp->len,
1415 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1416 0, packet->data, packet->len, FALSE);
1418 silc_buffer_free(packet);
1419 silc_buffer_free(idp);
1425 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1427 SilcServer server = cmd->server;
1428 char *nick = NULL, *server_name = NULL;
1429 int count = 0, clients_count = 0;
1430 SilcClientEntry *clients = NULL, entry;
1431 SilcClientID **client_id = NULL;
1432 unsigned int client_id_count = 0;
1435 /* Protocol dictates that we must always send the received IDENTIFY request
1436 to our router if we are normal server, so let's do it now unless we
1437 are standalone. We will not send any replies to the client until we
1438 have received reply from the router. */
1439 if (server->server_type == SILC_SERVER &&
1440 !cmd->pending && !server->standalone) {
1442 unsigned short old_ident;
1444 old_ident = silc_command_get_ident(cmd->payload);
1445 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1446 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1448 /* Send IDENTIFY command to our router */
1449 silc_server_packet_send(server, (SilcSocketConnection)
1450 server->router->connection,
1451 SILC_PACKET_COMMAND, cmd->packet->flags,
1452 tmpbuf->data, tmpbuf->len, TRUE);
1454 /* Reprocess this packet after received reply from router */
1455 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1456 silc_command_get_ident(cmd->payload),
1457 silc_server_command_destructor,
1458 silc_server_command_identify,
1459 silc_server_command_dup(cmd));
1460 cmd->pending = TRUE;
1462 silc_command_set_ident(cmd->payload, old_ident);
1464 silc_buffer_free(tmpbuf);
1469 /* We are ready to process the command request. Let's search for the
1470 requested client and send reply to the requesting client. */
1472 /* Parse the IDENTIFY request */
1473 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1474 &nick, &server_name, &count,
1475 SILC_COMMAND_IDENTIFY))
1478 /* Get all clients matching that ID or nickname from local list */
1479 if (client_id_count) {
1480 /* Check all Client ID's received in the command packet */
1481 for (i = 0; i < client_id_count; i++) {
1482 entry = silc_idlist_find_client_by_id(server->local_list,
1483 client_id[i], NULL);
1485 clients = silc_realloc(clients, sizeof(*clients) *
1486 (clients_count + 1));
1487 clients[clients_count++] = entry;
1491 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1495 clients = silc_idlist_get_clients_by_hash(server->local_list,
1496 nick, server->md5hash,
1500 /* Check global list as well */
1502 if (client_id_count) {
1503 /* Check all Client ID's received in the command packet */
1504 for (i = 0; i < client_id_count; i++) {
1505 entry = silc_idlist_find_client_by_id(server->global_list,
1506 client_id[i], NULL);
1508 clients = silc_realloc(clients, sizeof(*clients) *
1509 (clients_count + 1));
1510 clients[clients_count++] = entry;
1514 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1518 clients = silc_idlist_get_clients_by_hash(server->global_list,
1519 nick, server->md5hash,
1525 /* Such a client really does not exist in the SILC network. */
1526 if (!client_id_count) {
1527 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1528 SILC_STATUS_ERR_NO_SUCH_NICK,
1529 3, nick, strlen(nick));
1531 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1532 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1533 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1534 2, idp->data, idp->len);
1535 silc_buffer_free(idp);
1540 /* Check that all mandatory fields are present and request those data
1541 from the server who owns the client if necessary. */
1542 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1547 /* Send the command reply to the client */
1548 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1551 if (client_id_count) {
1552 for (i = 0; i < client_id_count; i++)
1553 silc_free(client_id[i]);
1554 silc_free(client_id);
1561 silc_free(server_name);
1567 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1569 SilcServer server = cmd->server;
1570 char *nick = NULL, *server_name = NULL;
1571 int count = 0, clients_count = 0;
1572 SilcClientEntry *clients = NULL, entry;
1573 SilcClientID **client_id = NULL;
1574 unsigned int client_id_count = 0;
1577 /* Parse the IDENTIFY request */
1578 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1579 &nick, &server_name, &count,
1580 SILC_COMMAND_IDENTIFY))
1583 /* Process the command request. Let's search for the requested client and
1584 send reply to the requesting server. */
1586 if (client_id_count) {
1587 /* Check all Client ID's received in the command packet */
1588 for (i = 0; i < client_id_count; i++) {
1589 entry = silc_idlist_find_client_by_id(server->local_list,
1590 client_id[i], NULL);
1592 clients = silc_realloc(clients, sizeof(*clients) *
1593 (clients_count + 1));
1594 clients[clients_count++] = entry;
1598 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1602 clients = silc_idlist_get_clients_by_hash(server->local_list,
1603 nick, server->md5hash,
1607 /* If we are router we will check our global list as well. */
1608 if (!clients && server->server_type == SILC_ROUTER) {
1609 if (client_id_count) {
1610 /* Check all Client ID's received in the command packet */
1611 for (i = 0; i < client_id_count; i++) {
1612 entry = silc_idlist_find_client_by_id(server->global_list,
1613 client_id[i], NULL);
1615 clients = silc_realloc(clients, sizeof(*clients) *
1616 (clients_count + 1));
1617 clients[clients_count++] = entry;
1621 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1625 clients = silc_idlist_get_clients_by_hash(server->global_list,
1626 nick, server->md5hash,
1632 /* Such a client really does not exist in the SILC network. */
1633 if (!client_id_count) {
1634 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1635 SILC_STATUS_ERR_NO_SUCH_NICK,
1636 3, nick, strlen(nick));
1638 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1639 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1640 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1641 2, idp->data, idp->len);
1642 silc_buffer_free(idp);
1647 /* Check that all mandatory fields are present and request those data
1648 from the server who owns the client if necessary. */
1649 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1654 /* Send the command reply */
1655 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1658 if (client_id_count) {
1659 for (i = 0; i < client_id_count; i++)
1660 silc_free(client_id[i]);
1661 silc_free(client_id);
1668 silc_free(server_name);
1673 SILC_SERVER_CMD_FUNC(identify)
1675 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1678 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1680 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1681 ret = silc_server_command_identify_from_client(cmd);
1682 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1683 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1684 ret = silc_server_command_identify_from_server(cmd);
1687 silc_server_command_free(cmd);
1690 /* Checks string for bad characters and returns TRUE if they are found. */
1692 static int silc_server_command_bad_chars(char *nick)
1694 if (strchr(nick, '\\')) return TRUE;
1695 if (strchr(nick, '\"')) return TRUE;
1696 if (strchr(nick, '´')) return TRUE;
1697 if (strchr(nick, '`')) return TRUE;
1698 if (strchr(nick, '\'')) return TRUE;
1699 if (strchr(nick, '*')) return TRUE;
1700 if (strchr(nick, '/')) return TRUE;
1701 if (strchr(nick, '@')) return TRUE;
1706 /* Server side of command NICK. Sets nickname for user. Setting
1707 nickname causes generation of a new client ID for the client. The
1708 new client ID is sent to the client after changing the nickname. */
1710 SILC_SERVER_CMD_FUNC(nick)
1712 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1713 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1714 SilcServer server = cmd->server;
1715 SilcBuffer packet, nidp, oidp;
1716 SilcClientID *new_id;
1718 unsigned short ident = silc_command_get_ident(cmd->payload);
1720 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1723 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1725 /* Check nickname */
1726 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1727 if (silc_server_command_bad_chars(nick) == TRUE) {
1728 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1729 SILC_STATUS_ERR_BAD_NICKNAME);
1733 if (strlen(nick) > 128)
1736 /* Create new Client ID */
1737 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1738 cmd->server->md5hash, nick,
1741 /* Send notify about nickname change to our router. We send the new
1742 ID and ask to replace it with the old one. If we are router the
1743 packet is broadcasted. Send NICK_CHANGE notify. */
1744 if (!server->standalone)
1745 silc_server_send_notify_nick_change(server, server->router->connection,
1746 server->server_type == SILC_SERVER ?
1747 FALSE : TRUE, client->id,
1748 new_id, SILC_ID_CLIENT_LEN);
1750 /* Remove old cache entry */
1751 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1754 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1758 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1759 silc_free(client->id);
1762 /* Save the nickname as this client is our local client */
1763 if (client->nickname)
1764 silc_free(client->nickname);
1766 client->nickname = strdup(nick);
1767 client->id = new_id;
1769 /* Update client cache */
1770 silc_idcache_add(server->local_list->clients, client->nickname,
1771 strlen(client->nickname), SILC_ID_CLIENT, client->id,
1772 (void *)client, TRUE, FALSE);
1774 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1776 /* Send NICK_CHANGE notify to the client's channels */
1777 silc_server_send_notify_on_channels(server, NULL, client,
1778 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1779 oidp->data, oidp->len,
1780 nidp->data, nidp->len);
1782 /* Send the new Client ID as reply command back to client */
1783 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1784 SILC_STATUS_OK, ident, 1,
1785 2, nidp->data, nidp->len);
1786 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1787 0, packet->data, packet->len, FALSE);
1789 silc_buffer_free(packet);
1790 silc_buffer_free(nidp);
1791 silc_buffer_free(oidp);
1794 silc_server_command_free(cmd);
1797 /* Sends the LIST command reply */
1800 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1801 SilcChannelEntry *lch,
1802 unsigned int lch_count,
1803 SilcChannelEntry *gch,
1804 unsigned int gch_count)
1807 SilcBuffer packet, idp;
1808 SilcChannelEntry entry;
1809 SilcCommandStatus status;
1810 unsigned short ident = silc_command_get_ident(cmd->payload);
1812 unsigned char usercount[4];
1815 for (i = 0; i < lch_count; i++)
1816 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1818 for (i = 0; i < gch_count; i++)
1819 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1822 status = SILC_STATUS_OK;
1823 if ((lch_count + gch_count) > 1)
1824 status = SILC_STATUS_LIST_START;
1827 for (i = 0; i < lch_count; i++) {
1834 status = SILC_STATUS_LIST_ITEM;
1836 if (i == lch_count - 1 && gch_count)
1838 if (lch_count > 1 && i == lch_count - 1)
1839 status = SILC_STATUS_LIST_END;
1841 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1843 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1844 topic = "*private*";
1845 memset(usercount, 0, sizeof(usercount));
1847 topic = entry->topic;
1848 users = silc_list_count(entry->user_list);
1849 SILC_PUT32_MSB(users, usercount);
1852 /* Send the reply */
1855 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1857 2, idp->data, idp->len,
1858 3, entry->channel_name,
1859 strlen(entry->channel_name),
1860 4, topic, strlen(topic),
1864 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1866 2, idp->data, idp->len,
1867 3, entry->channel_name,
1868 strlen(entry->channel_name),
1870 silc_server_packet_send(cmd->server, cmd->sock,
1871 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1872 packet->len, FALSE);
1873 silc_buffer_free(packet);
1874 silc_buffer_free(idp);
1877 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1880 for (i = 0; i < gch_count; i++) {
1887 status = SILC_STATUS_LIST_ITEM;
1889 if (gch_count > 1 && i == lch_count - 1)
1890 status = SILC_STATUS_LIST_END;
1892 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1894 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1895 topic = "*private*";
1896 memset(usercount, 0, sizeof(usercount));
1898 topic = entry->topic;
1899 users = silc_list_count(entry->user_list);
1900 SILC_PUT32_MSB(users, usercount);
1903 /* Send the reply */
1906 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1908 2, idp->data, idp->len,
1909 3, entry->channel_name,
1910 strlen(entry->channel_name),
1911 4, topic, strlen(topic),
1915 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1917 2, idp->data, idp->len,
1918 3, entry->channel_name,
1919 strlen(entry->channel_name),
1921 silc_server_packet_send(cmd->server, cmd->sock,
1922 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1923 packet->len, FALSE);
1924 silc_buffer_free(packet);
1925 silc_buffer_free(idp);
1929 /* Server side of LIST command. This lists the channel of the requested
1930 server. Secret channels are not listed. */
1932 SILC_SERVER_CMD_FUNC(list)
1934 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1935 SilcServer server = cmd->server;
1936 SilcChannelID *channel_id = NULL;
1938 unsigned int tmp_len;
1939 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1940 unsigned int lch_count = 0, gch_count = 0;
1942 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1944 /* Get Channel ID */
1945 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1947 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1950 SILC_STATUS_ERR_NO_CHANNEL_ID);
1955 /* Get the channels from local list */
1956 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1959 /* Get the channels from global list if we are router */
1960 if (server->server_type == SILC_ROUTER)
1961 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1964 /* Send the reply */
1965 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
1966 gchannels, gch_count);
1969 silc_server_command_free(cmd);
1972 /* Server side of TOPIC command. Sets topic for channel and/or returns
1973 current topic to client. */
1975 SILC_SERVER_CMD_FUNC(topic)
1977 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1978 SilcServer server = cmd->server;
1979 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1980 SilcChannelID *channel_id;
1981 SilcChannelEntry channel;
1982 SilcChannelClientEntry chl;
1983 SilcBuffer packet, idp;
1985 unsigned int argc, tmp_len;
1986 unsigned short ident = silc_command_get_ident(cmd->payload);
1988 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1990 argc = silc_argument_get_arg_num(cmd->args);
1992 /* Get Channel ID */
1993 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1995 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1996 SILC_STATUS_ERR_NO_CHANNEL_ID);
1999 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2001 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2002 SILC_STATUS_ERR_NO_CHANNEL_ID);
2006 /* Check whether the channel exists */
2007 channel = silc_idlist_find_channel_by_id(server->local_list,
2010 channel = silc_idlist_find_channel_by_id(server->global_list,
2013 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2014 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2021 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2023 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2024 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2028 if (strlen(tmp) > 256) {
2029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2030 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2034 /* See whether has rights to change topic */
2035 silc_list_start(channel->user_list);
2036 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2037 if (chl->client == client)
2040 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2041 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2043 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2048 /* Set the topic for channel */
2050 silc_free(channel->topic);
2051 channel->topic = strdup(tmp);
2053 /* Send TOPIC_SET notify type to the network */
2054 if (!server->standalone)
2055 silc_server_send_notify_topic_set(server, server->router->connection,
2056 server->server_type == SILC_ROUTER ?
2057 TRUE : FALSE, channel, client->id,
2058 SILC_ID_CLIENT_LEN, channel->topic);
2060 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2062 /* Send notify about topic change to all clients on the channel */
2063 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2064 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2065 idp->data, idp->len,
2066 channel->topic, strlen(channel->topic));
2067 silc_buffer_free(idp);
2070 /* Send the topic to client as reply packet */
2071 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2073 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2074 SILC_STATUS_OK, ident, 2,
2075 2, idp->data, idp->len,
2077 strlen(channel->topic));
2079 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2080 SILC_STATUS_OK, ident, 1,
2081 2, idp->data, idp->len);
2082 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2083 0, packet->data, packet->len, FALSE);
2085 silc_buffer_free(packet);
2086 silc_buffer_free(idp);
2087 silc_free(channel_id);
2090 silc_server_command_free(cmd);
2093 /* Server side of INVITE command. Invites some client to join some channel.
2094 This command is also used to manage the invite list of the channel. */
2096 SILC_SERVER_CMD_FUNC(invite)
2098 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2099 SilcServer server = cmd->server;
2100 SilcSocketConnection sock = cmd->sock, dest_sock;
2101 SilcChannelClientEntry chl;
2102 SilcClientEntry sender, dest;
2103 SilcClientID *dest_id = NULL;
2104 SilcChannelEntry channel;
2105 SilcChannelID *channel_id = NULL;
2106 SilcIDListData idata;
2107 SilcBuffer idp, idp2, packet;
2108 unsigned char *tmp, *add, *del;
2110 unsigned short ident = silc_command_get_ident(cmd->payload);
2112 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2114 /* Get Channel ID */
2115 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2117 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2118 SILC_STATUS_ERR_NO_CHANNEL_ID);
2121 channel_id = silc_id_payload_parse_id(tmp, len);
2123 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2124 SILC_STATUS_ERR_NO_CHANNEL_ID);
2128 /* Get the channel entry */
2129 channel = silc_idlist_find_channel_by_id(server->local_list,
2132 channel = silc_idlist_find_channel_by_id(server->global_list,
2135 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2136 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2141 /* Check whether the sender of this command is on the channel. */
2142 sender = (SilcClientEntry)sock->user_data;
2143 if (!silc_server_client_on_channel(sender, channel)) {
2144 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2145 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2149 /* Check whether the channel is invite-only channel. If yes then the
2150 sender of this command must be at least channel operator. */
2151 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2152 silc_list_start(channel->user_list);
2153 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2154 if (chl->client == sender) {
2155 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2156 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2157 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2164 /* Get destination client ID */
2165 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2169 dest_id = silc_id_payload_parse_id(tmp, len);
2171 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2172 SILC_STATUS_ERR_NO_CLIENT_ID);
2176 /* Get the client entry */
2177 dest = silc_server_get_client_resolve(server, dest_id);
2179 if (server->server_type == SILC_ROUTER) {
2180 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2181 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2185 /* The client info is being resolved. Reprocess this packet after
2186 receiving the reply to the query. */
2187 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2189 silc_server_command_destructor,
2190 silc_server_command_invite,
2191 silc_server_command_dup(cmd));
2192 cmd->pending = TRUE;
2193 silc_free(channel_id);
2198 /* Check whether the requested client is already on the channel. */
2199 if (silc_server_client_on_channel(dest, channel)) {
2200 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2201 SILC_STATUS_ERR_USER_ON_CHANNEL);
2205 /* Get route to the client */
2206 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2208 memset(invite, 0, sizeof(invite));
2209 strncat(invite, dest->nickname, strlen(dest->nickname));
2210 strncat(invite, "!", 1);
2211 strncat(invite, dest->username, strlen(dest->username));
2212 if (!strchr(dest->username, '@')) {
2213 strncat(invite, "@", 1);
2214 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2217 len = strlen(invite);
2218 if (!channel->invite_list)
2219 channel->invite_list = silc_calloc(len + 2,
2220 sizeof(*channel->invite_list));
2222 channel->invite_list = silc_realloc(channel->invite_list,
2223 sizeof(*channel->invite_list) *
2225 strlen(channel->invite_list) + 2));
2226 strncat(channel->invite_list, invite, len);
2227 strncat(channel->invite_list, ",", 1);
2229 /* Send notify to the client that is invited to the channel */
2230 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2231 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2232 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2234 SILC_NOTIFY_TYPE_INVITE, 3,
2235 idp->data, idp->len,
2236 channel->channel_name,
2237 strlen(channel->channel_name),
2238 idp2->data, idp2->len);
2239 silc_buffer_free(idp);
2240 silc_buffer_free(idp2);
2243 /* Add the client to the invite list of the channel */
2244 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2246 if (!channel->invite_list)
2247 channel->invite_list = silc_calloc(len + 2,
2248 sizeof(*channel->invite_list));
2250 channel->invite_list = silc_realloc(channel->invite_list,
2251 sizeof(*channel->invite_list) *
2253 strlen(channel->invite_list) + 2));
2254 if (add[len - 1] == ',')
2255 add[len - 1] = '\0';
2257 strncat(channel->invite_list, add, len);
2258 strncat(channel->invite_list, ",", 1);
2261 /* Get the invite to be removed and remove it from the list */
2262 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2263 if (del && channel->invite_list) {
2264 char *start, *end, *n;
2266 if (!strncmp(channel->invite_list, del,
2267 strlen(channel->invite_list) - 1)) {
2268 silc_free(channel->invite_list);
2269 channel->invite_list = NULL;
2271 start = strstr(channel->invite_list, del);
2272 if (start && strlen(start) >= len) {
2274 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2275 strncat(n, channel->invite_list, start - channel->invite_list);
2276 strncat(n, end + 1, ((channel->invite_list +
2277 strlen(channel->invite_list)) - end) - 1);
2278 silc_free(channel->invite_list);
2279 channel->invite_list = n;
2284 /* Send notify to the primary router */
2285 if (!server->standalone)
2286 silc_server_send_notify_invite(server, server->router->connection,
2287 server->server_type == SILC_ROUTER ?
2288 TRUE : FALSE, channel,
2289 sender->id, SILC_ID_CLIENT_LEN,
2292 /* Send command reply */
2293 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2294 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2295 SILC_STATUS_OK, ident, 2,
2297 3, channel->invite_list,
2298 channel->invite_list ?
2299 strlen(channel->invite_list) :
2301 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2302 packet->data, packet->len, FALSE);
2303 silc_buffer_free(packet);
2309 silc_free(channel_id);
2310 silc_server_command_free(cmd);
2315 SilcSocketConnection sock;
2319 /* Quits connection to client. This gets called if client won't
2320 close the connection even when it has issued QUIT command. */
2322 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2324 QuitInternal q = (QuitInternal)context;
2326 /* Free all client specific data, such as client entry and entires
2327 on channels this client may be on. */
2328 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2330 q->sock->user_data = NULL;
2332 /* Close the connection on our side */
2333 silc_server_close_connection(q->server, q->sock);
2335 silc_free(q->signoff);
2339 /* Quits SILC session. This is the normal way to disconnect client. */
2341 SILC_SERVER_CMD_FUNC(quit)
2343 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2344 SilcServer server = cmd->server;
2345 SilcSocketConnection sock = cmd->sock;
2347 unsigned char *tmp = NULL;
2348 unsigned int len = 0;
2350 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2352 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2355 /* Get destination ID */
2356 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2360 q = silc_calloc(1, sizeof(*q));
2363 q->signoff = tmp ? strdup(tmp) : NULL;
2365 /* We quit the connection with little timeout */
2366 silc_task_register(server->timeout_queue, sock->sock,
2367 silc_server_command_quit_cb, (void *)q,
2368 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2371 silc_server_command_free(cmd);
2374 /* Server side of command KILL. This command is used by router operator
2375 to remove an client from the SILC Network temporarily. */
2377 SILC_SERVER_CMD_FUNC(kill)
2379 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2380 SilcServer server = cmd->server;
2381 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2382 SilcClientEntry remote_client;
2383 SilcClientID *client_id;
2384 unsigned char *tmp, *comment;
2385 unsigned int tmp_len, tmp_len2;
2387 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2389 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2392 /* KILL command works only on router */
2393 if (server->server_type != SILC_ROUTER) {
2394 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2395 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2399 /* Check whether client has the permissions. */
2400 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2401 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2402 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2406 /* Get the client ID */
2407 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2410 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2413 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2416 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2420 /* Get the client entry */
2421 remote_client = silc_idlist_find_client_by_id(server->local_list,
2423 if (!remote_client) {
2424 remote_client = silc_idlist_find_client_by_id(server->global_list,
2426 if (!remote_client) {
2427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2428 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2434 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2438 /* Send reply to the sender */
2439 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2442 /* Send the KILL notify packets. First send it to the channel, then
2443 to our primary router and then directly to the client who is being
2444 killed right now. */
2446 /* Send KILLED notify to the channels. It is not sent to the client
2447 as it will be sent differently destined directly to the client and not
2449 silc_server_send_notify_on_channels(server, remote_client,
2450 remote_client, SILC_NOTIFY_TYPE_KILLED,
2453 comment, comment ? tmp_len2 : 0);
2455 /* Send KILLED notify to primary route */
2456 if (!server->standalone)
2457 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2458 remote_client->id, SILC_ID_CLIENT_LEN,
2461 /* Send KILLED notify to the client directly */
2462 silc_server_send_notify_killed(server, remote_client->connection ?
2463 remote_client->connection :
2464 remote_client->router->connection, FALSE,
2465 remote_client->id, SILC_ID_CLIENT_LEN,
2468 /* Remove the client from all channels. This generates new keys to the
2469 channels as well. */
2470 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2473 /* Remove the client entry, If it is locally connected then we will also
2474 disconnect the client here */
2475 if (remote_client->data.registered && remote_client->connection) {
2476 /* Remove locally conneted client */
2477 SilcSocketConnection sock = remote_client->connection;
2478 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2479 silc_server_close_connection(server, sock);
2481 /* Remove remote client */
2482 if (!silc_idlist_del_client(server->global_list, remote_client))
2483 silc_idlist_del_client(server->local_list, remote_client);
2487 silc_server_command_free(cmd);
2490 /* Server side of command INFO. This sends information about us to
2491 the client. If client requested specific server we will send the
2492 command to that server. */
2494 SILC_SERVER_CMD_FUNC(info)
2496 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2497 SilcServer server = cmd->server;
2498 SilcBuffer packet, idp;
2499 char *dest_server, *server_info = NULL, *server_name;
2500 unsigned short ident = silc_command_get_ident(cmd->payload);
2501 SilcServerEntry entry = NULL;
2503 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
2505 /* Get server name */
2506 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2508 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2509 SILC_STATUS_ERR_NO_SUCH_SERVER);
2513 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2514 /* Send our reply */
2515 char info_string[256];
2517 memset(info_string, 0, sizeof(info_string));
2518 snprintf(info_string, sizeof(info_string),
2519 "location: %s server: %s admin: %s <%s>",
2520 server->config->admin_info->location,
2521 server->config->admin_info->server_type,
2522 server->config->admin_info->admin_name,
2523 server->config->admin_info->admin_email);
2525 server_info = info_string;
2526 entry = server->id_entry;
2528 /* Check whether we have this server cached */
2529 entry = silc_idlist_find_server_by_name(server->global_list,
2532 entry = silc_idlist_find_server_by_name(server->local_list,
2536 if (server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2537 /* Send to the server */
2539 unsigned short old_ident;
2541 old_ident = silc_command_get_ident(cmd->payload);
2542 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2543 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2545 silc_server_packet_send(server, entry->connection,
2546 SILC_PACKET_COMMAND, cmd->packet->flags,
2547 tmpbuf->data, tmpbuf->len, TRUE);
2549 /* Reprocess this packet after received reply from router */
2550 silc_server_command_pending(server, SILC_COMMAND_INFO,
2551 silc_command_get_ident(cmd->payload),
2552 silc_server_command_destructor,
2553 silc_server_command_info,
2554 silc_server_command_dup(cmd));
2555 cmd->pending = TRUE;
2556 silc_command_set_ident(cmd->payload, old_ident);
2557 silc_buffer_free(tmpbuf);
2561 if (!entry && !cmd->pending && !server->standalone) {
2562 /* Send to the primary router */
2564 unsigned short old_ident;
2566 old_ident = silc_command_get_ident(cmd->payload);
2567 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2568 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2570 silc_server_packet_send(server, server->router->connection,
2571 SILC_PACKET_COMMAND, cmd->packet->flags,
2572 tmpbuf->data, tmpbuf->len, TRUE);
2574 /* Reprocess this packet after received reply from router */
2575 silc_server_command_pending(server, SILC_COMMAND_INFO,
2576 silc_command_get_ident(cmd->payload),
2577 silc_server_command_destructor,
2578 silc_server_command_info,
2579 silc_server_command_dup(cmd));
2580 cmd->pending = TRUE;
2581 silc_command_set_ident(cmd->payload, old_ident);
2582 silc_buffer_free(tmpbuf);
2588 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2589 SILC_STATUS_ERR_NO_SUCH_SERVER);
2593 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2595 server_info = entry->server_info;
2596 server_name = dest_server;
2598 /* Send the reply */
2599 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2600 SILC_STATUS_OK, ident, 3,
2601 2, idp->data, idp->len,
2603 strlen(server_name),
2605 strlen(server_info));
2606 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2607 packet->data, packet->len, FALSE);
2609 silc_buffer_free(packet);
2610 silc_buffer_free(idp);
2613 silc_server_command_free(cmd);
2616 /* Server side of command PING. This just replies to the ping. */
2618 SILC_SERVER_CMD_FUNC(ping)
2620 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2621 SilcServer server = cmd->server;
2626 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2629 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2631 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2632 SILC_STATUS_ERR_NO_SERVER_ID);
2635 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2639 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2640 /* Send our reply */
2641 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2644 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2645 SILC_STATUS_ERR_NO_SUCH_SERVER);
2652 silc_server_command_free(cmd);
2655 /* Internal routine to join channel. The channel sent to this function
2656 has been either created or resolved from ID lists. This joins the sent
2657 client to the channel. */
2659 static void silc_server_command_join_channel(SilcServer server,
2660 SilcServerCommandContext cmd,
2661 SilcChannelEntry channel,
2662 SilcClientID *client_id,
2666 SilcSocketConnection sock = cmd->sock;
2668 unsigned int tmp_len, user_count;
2669 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2670 SilcClientEntry client;
2671 SilcChannelClientEntry chl;
2672 SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
2673 unsigned short ident = silc_command_get_ident(cmd->payload);
2676 SILC_LOG_DEBUG(("Start"));
2681 /* Get the client entry */
2682 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2683 client = (SilcClientEntry)sock->user_data;
2685 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2692 * Check channel modes
2695 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2696 strncat(check, client->nickname, strlen(client->nickname));
2697 if (!strchr(client->nickname, '@')) {
2698 strncat(check, "@", 1);
2699 strncat(check, server->server_name, strlen(server->server_name));
2701 strncat(check, "!", 1);
2702 strncat(check, client->username, strlen(client->username));
2703 if (!strchr(client->username, '@')) {
2704 strncat(check, "@", 1);
2705 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2709 /* Check invite list if channel is invite-only channel */
2710 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
2711 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2712 if (!channel->invite_list) {
2713 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2714 SILC_STATUS_ERR_NOT_INVITED);
2718 if (!silc_string_match(channel->invite_list, check)) {
2719 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2720 SILC_STATUS_ERR_NOT_INVITED);
2725 /* Check ban list if it exists. If the client's nickname, server,
2726 username and/or hostname is in the ban list the access to the
2727 channel is denied. */
2728 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2729 if (silc_string_match(channel->ban_list, check)) {
2730 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2731 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2736 /* Get passphrase */
2737 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2739 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2740 memcpy(passphrase, tmp, tmp_len);
2743 /* Check the channel passphrase if set. */
2744 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2745 if (!passphrase || memcmp(channel->passphrase, passphrase,
2746 strlen(channel->passphrase))) {
2747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2748 SILC_STATUS_ERR_BAD_PASSWORD);
2753 /* Check user count limit if set. */
2754 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2755 if (silc_list_count(channel->user_list) + 1 >
2756 channel->user_limit) {
2757 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2758 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2764 * Client is allowed to join to the channel. Make it happen.
2767 /* Check whether the client already is on the channel */
2768 if (silc_server_client_on_channel(client, channel)) {
2769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2770 SILC_STATUS_ERR_USER_ON_CHANNEL);
2774 /* Generate new channel key as protocol dictates */
2775 if ((!created && silc_list_count(channel->user_list) > 0) ||
2776 !channel->channel_key)
2777 silc_server_create_channel_key(server, channel, 0);
2779 /* Send the channel key. This is broadcasted to the channel but is not
2780 sent to the client who is joining to the channel. */
2781 silc_server_send_channel_key(server, NULL, channel,
2782 server->server_type == SILC_ROUTER ?
2783 FALSE : !server->standalone);
2785 /* Join the client to the channel by adding it to channel's user list.
2786 Add also the channel to client entry's channels list for fast cross-
2788 chl = silc_calloc(1, sizeof(*chl));
2790 chl->client = client;
2791 chl->channel = channel;
2792 silc_list_add(channel->user_list, chl);
2793 silc_list_add(client->channels, chl);
2795 /* Get users on the channel */
2796 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2799 /* Encode Client ID Payload of the original client who wants to join */
2800 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2802 /* Encode command reply packet */
2803 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2804 SILC_PUT32_MSB(channel->mode, mode);
2805 SILC_PUT32_MSB(created, tmp2);
2806 SILC_PUT32_MSB(user_count, tmp3);
2807 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2808 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2809 strlen(channel->channel_key->
2811 channel->channel_key->cipher->name,
2812 channel->key_len / 8, channel->key);
2815 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2816 SILC_STATUS_OK, ident, 13,
2817 2, channel->channel_name,
2818 strlen(channel->channel_name),
2819 3, chidp->data, chidp->len,
2820 4, clidp->data, clidp->len,
2823 7, keyp->data, keyp->len,
2824 8, channel->ban_list,
2826 strlen(channel->ban_list) : 0,
2827 9, channel->invite_list,
2828 channel->invite_list ?
2829 strlen(channel->invite_list) : 0,
2832 strlen(channel->topic) : 0,
2833 11, channel->hmac->hmac->name,
2834 strlen(channel->hmac->hmac->name),
2836 13, user_list->data, user_list->len,
2837 14, mode_list->data,
2840 /* Send command reply */
2841 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2842 reply->data, reply->len, FALSE);
2844 if (!cmd->pending) {
2845 /* Send JOIN notify to locally connected clients on the channel */
2846 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2847 SILC_NOTIFY_TYPE_JOIN, 2,
2848 clidp->data, clidp->len,
2849 chidp->data, chidp->len);
2851 /* Send JOIN notify packet to our primary router */
2852 if (!server->standalone)
2853 silc_server_send_notify_join(server, server->router->connection,
2854 server->server_type == SILC_ROUTER ?
2855 TRUE : FALSE, channel, client->id,
2856 SILC_ID_CLIENT_LEN);
2859 silc_buffer_free(reply);
2860 silc_buffer_free(clidp);
2861 silc_buffer_free(chidp);
2862 silc_buffer_free(keyp);
2863 silc_buffer_free(user_list);
2864 silc_buffer_free(mode_list);
2868 silc_free(passphrase);
2871 /* Server side of command JOIN. Joins client into requested channel. If
2872 the channel does not exist it will be created. */
2874 SILC_SERVER_CMD_FUNC(join)
2876 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2877 SilcServer server = cmd->server;
2879 char *tmp, *channel_name = NULL, *cipher, *hmac;
2880 SilcChannelEntry channel;
2881 unsigned int umode = 0;
2882 int created = FALSE;
2883 SilcClientID *client_id;
2885 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2887 /* Get channel name */
2888 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2891 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2896 if (strlen(channel_name) > 256)
2897 channel_name[255] = '\0';
2899 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2900 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2901 SILC_STATUS_ERR_BAD_CHANNEL);
2902 silc_free(channel_name);
2906 /* Get Client ID of the client who is joining to the channel */
2907 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2909 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2910 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2913 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2915 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2916 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2920 /* Get cipher and hmac name */
2921 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2922 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2924 /* See if the channel exists */
2925 channel = silc_idlist_find_channel_by_name(server->local_list,
2926 channel_name, NULL);
2928 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2929 /* If this is coming from client the Client ID in the command packet must
2930 be same as the client's ID. */
2931 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2932 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2933 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2934 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2935 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2941 /* Channel not found */
2943 /* If we are standalone server we don't have a router, we just create
2944 the channel by ourselves. */
2945 if (server->standalone) {
2946 channel = silc_server_create_new_channel(server, server->id, cipher,
2947 hmac, channel_name, TRUE);
2948 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2953 /* The channel does not exist on our server. If we are normal server
2954 we will send JOIN command to our router which will handle the
2955 joining procedure (either creates the channel if it doesn't exist
2956 or joins the client to it). */
2957 if (server->server_type == SILC_SERVER) {
2959 unsigned short old_ident;
2961 old_ident = silc_command_get_ident(cmd->payload);
2962 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2963 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2965 /* Send JOIN command to our router */
2966 silc_server_packet_send(server, (SilcSocketConnection)
2967 server->router->connection,
2968 SILC_PACKET_COMMAND, cmd->packet->flags,
2969 tmpbuf->data, tmpbuf->len, TRUE);
2971 /* Reprocess this packet after received reply from router */
2972 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2973 silc_command_get_ident(cmd->payload),
2974 silc_server_command_destructor,
2975 silc_server_command_join,
2976 silc_server_command_dup(cmd));
2977 cmd->pending = TRUE;
2981 /* We are router and the channel does not seem exist so we will check
2982 our global list as well for the channel. */
2983 channel = silc_idlist_find_channel_by_name(server->global_list,
2984 channel_name, NULL);
2986 /* Channel really does not exist, create it */
2987 channel = silc_server_create_new_channel(server, server->id, cipher,
2988 hmac, channel_name, TRUE);
2989 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2996 /* Channel not found */
2998 /* If the command came from router and/or we are normal server then
2999 something went wrong with the joining as the channel was not found.
3000 We can't do anything else but ignore this. */
3001 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3002 server->server_type == SILC_SERVER)
3005 /* We are router and the channel does not seem exist so we will check
3006 our global list as well for the channel. */
3007 channel = silc_idlist_find_channel_by_name(server->global_list,
3008 channel_name, NULL);
3010 /* Channel really does not exist, create it */
3011 channel = silc_server_create_new_channel(server, server->id, cipher,
3012 hmac, channel_name, TRUE);
3013 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3019 /* If the channel does not have global users and is also empty it means the
3020 channel was created globally (by our router) and the client will be the
3021 channel founder and operator. */
3022 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3023 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3024 created = TRUE; /* Created globally by our router */
3027 /* Join to the channel */
3028 silc_server_command_join_channel(server, cmd, channel, client_id,
3031 silc_free(client_id);
3034 silc_server_command_free(cmd);
3037 /* Server side of command MOTD. Sends server's current "message of the
3038 day" to the client. */
3040 SILC_SERVER_CMD_FUNC(motd)
3042 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3043 SilcServer server = cmd->server;
3044 SilcBuffer packet, idp;
3045 char *motd, *dest_server;
3047 unsigned short ident = silc_command_get_ident(cmd->payload);
3049 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3051 /* Get server name */
3052 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3054 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3055 SILC_STATUS_ERR_NO_SUCH_SERVER);
3059 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3062 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3064 if (server->config && server->config->motd &&
3065 server->config->motd->motd_file) {
3067 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3072 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3073 SILC_STATUS_OK, ident, 2,
3079 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3080 SILC_STATUS_OK, ident, 1,
3084 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3085 packet->data, packet->len, FALSE);
3086 silc_buffer_free(packet);
3087 silc_buffer_free(idp);
3089 SilcServerEntry entry;
3091 /* Check whether we have this server cached */
3092 entry = silc_idlist_find_server_by_name(server->global_list,
3095 entry = silc_idlist_find_server_by_name(server->local_list,
3099 if (server->server_type == SILC_ROUTER && !cmd->pending &&
3100 entry && !entry->motd) {
3101 /* Send to the server */
3103 unsigned short old_ident;
3105 old_ident = silc_command_get_ident(cmd->payload);
3106 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3107 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3109 silc_server_packet_send(server, entry->connection,
3110 SILC_PACKET_COMMAND, cmd->packet->flags,
3111 tmpbuf->data, tmpbuf->len, TRUE);
3113 /* Reprocess this packet after received reply from router */
3114 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3115 silc_command_get_ident(cmd->payload),
3116 silc_server_command_destructor,
3117 silc_server_command_motd,
3118 silc_server_command_dup(cmd));
3119 cmd->pending = TRUE;
3120 silc_command_set_ident(cmd->payload, old_ident);
3121 silc_buffer_free(tmpbuf);
3125 if (!entry && !cmd->pending && !server->standalone) {
3126 /* Send to the primary router */
3128 unsigned short old_ident;
3130 old_ident = silc_command_get_ident(cmd->payload);
3131 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3132 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3134 silc_server_packet_send(server, server->router->connection,
3135 SILC_PACKET_COMMAND, cmd->packet->flags,
3136 tmpbuf->data, tmpbuf->len, TRUE);
3138 /* Reprocess this packet after received reply from router */
3139 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3140 silc_command_get_ident(cmd->payload),
3141 silc_server_command_destructor,
3142 silc_server_command_motd,
3143 silc_server_command_dup(cmd));
3144 cmd->pending = TRUE;
3145 silc_command_set_ident(cmd->payload, old_ident);
3146 silc_buffer_free(tmpbuf);
3151 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3152 SILC_STATUS_ERR_NO_SUCH_SERVER);
3156 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3159 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3160 SILC_STATUS_OK, ident, 2,
3163 strlen(entry->motd));
3165 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3166 SILC_STATUS_OK, ident, 1,
3169 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3170 packet->data, packet->len, FALSE);
3171 silc_buffer_free(packet);
3172 silc_buffer_free(idp);
3176 silc_server_command_free(cmd);
3179 /* Server side of command UMODE. Client can use this command to set/unset
3180 user mode. Client actually cannot set itself to be as server/router
3181 operator so this can be used only to unset the modes. */
3183 SILC_SERVER_CMD_FUNC(umode)
3185 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3186 SilcServer server = cmd->server;
3187 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3189 unsigned char *tmp_mask;
3191 unsigned short ident = silc_command_get_ident(cmd->payload);
3193 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3196 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3198 /* Get the client's mode mask */
3199 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3202 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3205 SILC_GET32_MSB(mask, tmp_mask);
3211 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3212 /* Cannot operator mode */
3213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3214 SILC_STATUS_ERR_PERM_DENIED);
3217 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3218 /* Remove the server operator rights */
3219 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3222 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3223 /* Cannot operator mode */
3224 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3225 SILC_STATUS_ERR_PERM_DENIED);
3228 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3229 /* Remove the router operator rights */
3230 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3233 /* Send UMODE change to primary router */
3234 if (!server->standalone)
3235 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3236 client->id, SILC_ID_CLIENT_LEN,
3239 /* Send command reply to sender */
3240 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3241 SILC_STATUS_OK, ident, 1,
3243 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3244 packet->data, packet->len, FALSE);
3245 silc_buffer_free(packet);
3248 silc_server_command_free(cmd);
3251 /* Checks that client has rights to add or remove channel modes. If any
3252 of the checks fails FALSE is returned. */
3254 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3255 SilcChannelClientEntry client,
3258 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3259 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3261 /* Check whether has rights to change anything */
3262 if (!is_op && !is_fo)
3265 /* Check whether has rights to change everything */
3269 /* We know that client is channel operator, check that they are not
3270 changing anything that requires channel founder rights. Rest of the
3271 modes are available automatically for channel operator. */
3273 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3274 if (is_op && !is_fo)
3277 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3278 if (is_op && !is_fo)
3283 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3284 if (is_op && !is_fo)
3287 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3288 if (is_op && !is_fo)
3293 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3294 if (is_op && !is_fo)
3297 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3298 if (is_op && !is_fo)
3306 /* Server side command of CMODE. Changes channel mode */
3308 SILC_SERVER_CMD_FUNC(cmode)
3310 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3311 SilcServer server = cmd->server;
3312 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3313 SilcChannelID *channel_id;
3314 SilcChannelEntry channel;
3315 SilcChannelClientEntry chl;
3316 SilcBuffer packet, cidp;
3317 unsigned char *tmp, *tmp_id, *tmp_mask;
3318 unsigned int argc, mode_mask, tmp_len, tmp_len2;
3319 unsigned short ident = silc_command_get_ident(cmd->payload);
3321 SILC_LOG_DEBUG(("Start"));
3323 argc = silc_argument_get_arg_num(cmd->args);
3325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3326 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3331 SILC_STATUS_ERR_TOO_MANY_PARAMS);
3335 /* Get Channel ID */
3336 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3338 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3339 SILC_STATUS_ERR_NO_CHANNEL_ID);
3342 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3345 SILC_STATUS_ERR_NO_CHANNEL_ID);
3349 /* Get the channel mode mask */
3350 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3353 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3356 SILC_GET32_MSB(mode_mask, tmp_mask);
3358 /* Get channel entry */
3359 channel = silc_idlist_find_channel_by_id(server->local_list,
3362 channel = silc_idlist_find_channel_by_id(server->global_list,
3365 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3366 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3371 /* Check whether this client is on the channel */
3372 if (!silc_server_client_on_channel(client, channel)) {
3373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3374 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3378 /* Get entry to the channel user list */
3379 silc_list_start(channel->user_list);
3380 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3381 if (chl->client == client)
3384 /* Check that client has rights to change any requested channel modes */
3385 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3387 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3392 * Check the modes. Modes that requires nothing special operation are
3396 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3397 /* Channel uses private keys to protect traffic. Client(s) has set the
3398 key locally they want to use, server does not know that key. */
3399 /* Nothing interesting to do here now */
3401 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3402 /* The mode is removed and we need to generate and distribute
3403 new channel key. Clients are not using private channel keys
3404 anymore after this. */
3406 /* XXX Duplicated code, make own function for this!! LEAVE uses this
3409 /* Re-generate channel key */
3410 silc_server_create_channel_key(server, channel, 0);
3412 /* Encode channel key payload to be distributed on the channel */
3414 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3415 strlen(channel->channel_key->
3417 channel->channel_key->cipher->name,
3418 channel->key_len / 8, channel->key);
3420 /* If we are normal server then we will send it to our router. If we
3421 are router we will send it to all local servers that has clients on
3423 if (server->server_type == SILC_SERVER) {
3424 if (!server->standalone)
3425 silc_server_packet_send(server,
3426 cmd->server->router->connection,
3427 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3433 /* Send to locally connected clients on the channel */
3434 silc_server_packet_send_local_channel(server, channel,
3435 SILC_PACKET_CHANNEL_KEY, 0,
3436 packet->data, packet->len, FALSE);
3437 silc_buffer_free(packet);
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 */
3491 unsigned int key_len;
3494 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
3496 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3497 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3501 /* XXX Duplicated code, make own function for this!! */
3503 /* Delete old cipher and allocate the new one */
3504 silc_cipher_free(channel->channel_key);
3505 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
3506 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3507 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3510 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
3512 /* Re-generate channel key */
3513 silc_server_create_channel_key(server, channel, key_len);
3515 /* Encode channel key payload to be distributed on the channel */
3517 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3518 strlen(channel->channel_key->
3520 channel->channel_key->cipher->name,
3521 channel->key_len / 8, channel->key);
3523 /* If we are normal server then we will send it to our router. If we
3524 are router we will send it to all local servers that has clients on
3526 if (server->server_type == SILC_SERVER) {
3527 if (!server->standalone)
3528 silc_server_packet_send(server,
3529 cmd->server->router->connection,
3530 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3536 /* Send to locally connected clients on the channel */
3537 silc_server_packet_send_local_channel(server, channel,
3538 SILC_PACKET_CHANNEL_KEY, 0,
3539 packet->data, packet->len, FALSE);
3540 silc_buffer_free(packet);
3543 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3544 /* Cipher mode is unset. Remove the cipher and revert back to
3546 char *cipher = channel->channel_key->cipher->name;
3548 /* Generate new cipher and key for the channel */
3550 /* XXX Duplicated code, make own function for this!! */
3552 /* Delete old cipher and allocate default one */
3553 silc_cipher_free(channel->channel_key);
3554 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3555 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3556 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3560 /* Re-generate channel key */
3561 silc_server_create_channel_key(server, channel, 0);
3563 /* Encode channel key payload to be distributed on the channel */
3565 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3566 strlen(channel->channel_key->
3568 channel->channel_key->cipher->name,
3569 channel->key_len / 8, channel->key);
3571 /* If we are normal server then we will send it to our router. If we
3572 are router we will send it to all local servers that has clients on
3574 if (server->server_type == SILC_SERVER) {
3575 if (!server->standalone)
3576 silc_server_packet_send(server,
3577 cmd->server->router->connection,
3578 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3584 /* Send to locally connected clients on the channel */
3585 silc_server_packet_send_local_channel(server, channel,
3586 SILC_PACKET_CHANNEL_KEY, 0,
3587 packet->data, packet->len, FALSE);
3588 silc_buffer_free(packet);
3592 /* Finally, set the mode */
3593 channel->mode = mode_mask;
3595 /* Send CMODE_CHANGE notify */
3596 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3597 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3598 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
3599 cidp->data, cidp->len,
3602 /* Set CMODE notify type to network */
3603 if (!server->standalone)
3604 silc_server_send_notify_cmode(server, server->router->connection,
3605 server->server_type == SILC_ROUTER ?
3606 TRUE : FALSE, channel,
3607 mode_mask, client->id, SILC_ID_CLIENT_LEN);
3609 /* Send command reply to sender */
3610 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3611 SILC_STATUS_OK, ident, 1,
3613 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3614 packet->data, packet->len, FALSE);
3616 silc_buffer_free(packet);
3617 silc_free(channel_id);
3621 silc_server_command_free(cmd);
3624 /* Server side of CUMODE command. Changes client's mode on a channel. */
3626 SILC_SERVER_CMD_FUNC(cumode)
3628 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3629 SilcServer server = cmd->server;
3630 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3631 SilcChannelID *channel_id;
3632 SilcClientID *client_id;
3633 SilcChannelEntry channel;
3634 SilcClientEntry target_client;
3635 SilcChannelClientEntry chl;
3636 SilcBuffer packet, idp;
3637 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3638 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3640 unsigned short ident = silc_command_get_ident(cmd->payload);
3642 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3644 /* Get Channel ID */
3645 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3647 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3648 SILC_STATUS_ERR_NO_CHANNEL_ID);
3651 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3653 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3654 SILC_STATUS_ERR_NO_CHANNEL_ID);
3658 /* Get channel entry */
3659 channel = silc_idlist_find_channel_by_id(server->local_list,
3662 channel = silc_idlist_find_channel_by_id(server->global_list,
3665 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3666 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3671 /* Check whether sender is on the channel */
3672 if (!silc_server_client_on_channel(client, channel)) {
3673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3674 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3678 /* Check that client has rights to change other's rights */
3679 silc_list_start(channel->user_list);
3680 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3681 if (chl->client == client) {
3682 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3683 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3685 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3689 sender_mask = chl->mode;
3694 /* Get the target client's channel mode mask */
3695 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3697 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3698 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3701 SILC_GET32_MSB(target_mask, tmp_mask);
3703 /* Get target Client ID */
3704 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3707 SILC_STATUS_ERR_NO_CLIENT_ID);
3710 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3712 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3713 SILC_STATUS_ERR_NO_CLIENT_ID);
3717 /* Get target client's entry */
3718 target_client = silc_idlist_find_client_by_id(server->local_list,
3720 if (!target_client) {
3721 target_client = silc_idlist_find_client_by_id(server->global_list,
3725 /* Check whether target client is on the channel */
3726 if (!silc_server_client_on_channel(target_client, channel)) {
3727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3728 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3732 /* Get entry to the channel user list */
3733 silc_list_start(channel->user_list);
3734 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3735 if (chl->client == target_client)
3742 /* If the target client is founder, no one else can change their mode
3744 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3745 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3746 SILC_STATUS_ERR_NOT_YOU);
3750 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3751 /* Cannot promote anyone to channel founder */
3752 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3753 SILC_STATUS_ERR_NOT_YOU);
3756 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3757 if (target_client == client) {
3758 /* Remove channel founder rights from itself */
3759 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3763 SILC_STATUS_ERR_NOT_YOU);
3769 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3770 /* Promote to operator */
3771 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3772 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3776 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3777 /* Demote to normal user */
3778 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3783 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3785 /* Send notify to channel, notify only if mode was actually changed. */
3787 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3788 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3789 idp->data, idp->len,
3793 /* Set CUMODE notify type to network */
3794 if (!server->standalone)
3795 silc_server_send_notify_cumode(server, server->router->connection,
3796 server->server_type == SILC_ROUTER ?
3797 TRUE : FALSE, channel,
3798 target_mask, client->id,
3801 SILC_ID_CLIENT_LEN);
3804 /* Send command reply to sender */
3805 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3806 SILC_STATUS_OK, ident, 2,
3808 3, tmp_id, tmp_len);
3809 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3810 packet->data, packet->len, FALSE);
3812 silc_buffer_free(packet);
3813 silc_free(channel_id);
3814 silc_free(client_id);
3815 silc_buffer_free(idp);
3818 silc_server_command_free(cmd);
3821 /* Server side of KICK command. Kicks client out of channel. */
3823 SILC_SERVER_CMD_FUNC(kick)
3825 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3826 SilcServer server = cmd->server;
3827 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3828 SilcClientEntry target_client;
3829 SilcChannelID *channel_id;
3830 SilcClientID *client_id;
3831 SilcChannelEntry channel;
3832 SilcChannelClientEntry chl;
3834 unsigned int tmp_len;
3835 unsigned char *tmp, *comment;
3837 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3839 /* Get Channel ID */
3840 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3842 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3843 SILC_STATUS_ERR_NO_CHANNEL_ID);
3846 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3849 SILC_STATUS_ERR_NO_CHANNEL_ID);
3853 /* Get channel entry */
3854 channel = silc_idlist_find_channel_by_id(server->local_list,
3857 channel = silc_idlist_find_channel_by_id(server->local_list,
3860 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3861 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3866 /* Check whether sender is on the channel */
3867 if (!silc_server_client_on_channel(client, channel)) {
3868 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3869 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3873 /* Check that the kicker is channel operator or channel founder */
3874 silc_list_start(channel->user_list);
3875 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3876 if (chl->client == client) {
3877 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3878 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3879 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3886 /* Get target Client ID */
3887 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3889 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3890 SILC_STATUS_ERR_NO_CLIENT_ID);
3893 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3895 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3896 SILC_STATUS_ERR_NO_CLIENT_ID);
3900 /* Get target client's entry */
3901 target_client = silc_idlist_find_client_by_id(server->local_list,
3903 if (!target_client) {
3904 target_client = silc_idlist_find_client_by_id(server->global_list,
3908 /* Check that the target client is not channel founder. Channel founder
3909 cannot be kicked from the channel. */
3910 silc_list_start(channel->user_list);
3911 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3912 if (chl->client == target_client) {
3913 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3915 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3922 /* Check whether target client is on the channel */
3923 if (!silc_server_client_on_channel(target_client, channel)) {
3924 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3925 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3931 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3935 /* Send command reply to sender */
3936 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3939 /* Send KICKED notify to local clients on the channel */
3940 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3941 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3942 SILC_NOTIFY_TYPE_KICKED,
3944 idp->data, idp->len,
3945 comment, comment ? strlen(comment) : 0);
3946 silc_buffer_free(idp);
3948 /* Remove the client from the channel. If the channel does not exist
3949 after removing the client then the client kicked itself off the channel
3950 and we don't have to send anything after that. */
3951 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3952 target_client, FALSE))
3955 /* Send KICKED notify to primary route */
3956 if (!server->standalone)
3957 silc_server_send_notify_kicked(server, server->router->connection,
3958 server->server_type == SILC_ROUTER ?
3959 TRUE : FALSE, channel,
3960 target_client->id, SILC_ID_CLIENT_LEN,
3963 /* Re-generate channel key */
3964 silc_server_create_channel_key(server, channel, 0);
3966 /* Send the channel key to the channel. The key of course is not sent
3967 to the client who was kicked off the channel. */
3968 silc_server_send_channel_key(server, target_client->connection, channel,
3969 server->server_type == SILC_ROUTER ?
3970 FALSE : !server->standalone);
3973 silc_server_command_free(cmd);
3976 /* Server side of OPER command. Client uses this comand to obtain server
3977 operator privileges to this server/router. */
3979 SILC_SERVER_CMD_FUNC(oper)
3981 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3982 SilcServer server = cmd->server;
3983 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3984 unsigned char *username, *auth;
3985 unsigned int tmp_len;
3986 SilcServerConfigSectionAdminConnection *admin;
3987 SilcIDListData idata = (SilcIDListData)client;
3989 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
3991 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3994 /* Get the username */
3995 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3998 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4002 /* Get the admin configuration */
4003 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4004 username, client->nickname);
4006 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4007 username, client->nickname);
4009 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4010 SILC_STATUS_ERR_AUTH_FAILED);
4015 /* Get the authentication payload */
4016 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4019 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4023 /* Verify the authentication data */
4024 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4025 admin->auth_data, admin->auth_data_len,
4026 idata->hash, client->id, SILC_ID_CLIENT)) {
4027 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4028 SILC_STATUS_ERR_AUTH_FAILED);
4032 /* Client is now server operator */
4033 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4035 /* Send UMODE change to primary router */
4036 if (!server->standalone)
4037 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4038 client->id, SILC_ID_CLIENT_LEN,
4041 /* Send reply to the sender */
4042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4046 silc_server_command_free(cmd);
4049 /* Server side of SILCOPER command. Client uses this comand to obtain router
4050 operator privileges to this router. */
4052 SILC_SERVER_CMD_FUNC(silcoper)
4054 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4055 SilcServer server = cmd->server;
4056 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4057 unsigned char *username, *auth;
4058 unsigned int tmp_len;
4059 SilcServerConfigSectionAdminConnection *admin;
4060 SilcIDListData idata = (SilcIDListData)client;
4062 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4064 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4067 /* Get the username */
4068 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4070 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4071 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4075 /* Get the admin configuration */
4076 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4077 username, client->nickname);
4079 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4080 username, client->nickname);
4082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4083 SILC_STATUS_ERR_AUTH_FAILED);
4088 /* Get the authentication payload */
4089 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4092 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4096 /* Verify the authentication data */
4097 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4098 admin->auth_data, admin->auth_data_len,
4099 idata->hash, client->id, SILC_ID_CLIENT)) {
4100 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4101 SILC_STATUS_ERR_AUTH_FAILED);
4105 /* Client is now router operator */
4106 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4108 /* Send UMODE change to primary router */
4109 if (!server->standalone)
4110 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4111 client->id, SILC_ID_CLIENT_LEN,
4114 /* Send reply to the sender */
4115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4119 silc_server_command_free(cmd);
4122 /* Server side command of CONNECT. Connects us to the specified remote
4123 server or router. */
4125 SILC_SERVER_CMD_FUNC(connect)
4127 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4128 SilcServer server = cmd->server;
4129 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4130 unsigned char *tmp, *host;
4131 unsigned int tmp_len;
4132 unsigned int port = SILC_PORT;
4134 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4136 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4139 /* Check whether client has the permissions. */
4140 if (client->mode == SILC_UMODE_NONE) {
4141 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4142 SILC_STATUS_ERR_NO_SERVER_PRIV);
4146 if (server->server_type == SILC_ROUTER &&
4147 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4148 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4149 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4153 /* Get the remote server */
4154 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4156 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4157 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4162 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4164 SILC_GET32_MSB(port, tmp);
4166 /* Create the connection. It is done with timeout and is async. */
4167 silc_server_create_connection(server, host, port);
4169 /* Send reply to the sender */
4170 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4174 silc_server_command_free(cmd);
4177 SILC_SERVER_CMD_FUNC(restart)
4181 /* Server side command of CLOSE. Closes connection to a specified server. */
4183 SILC_SERVER_CMD_FUNC(close)
4185 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4186 SilcServer server = cmd->server;
4187 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4188 SilcServerEntry server_entry;
4189 SilcSocketConnection sock;
4191 unsigned int tmp_len;
4192 unsigned char *name;
4193 unsigned int port = SILC_PORT;
4195 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4197 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4200 /* Check whether client has the permissions. */
4201 if (client->mode == SILC_UMODE_NONE) {
4202 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4203 SILC_STATUS_ERR_NO_SERVER_PRIV);
4207 /* Get the remote server */
4208 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4211 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4216 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4218 SILC_GET32_MSB(port, tmp);
4220 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4222 if (!server_entry) {
4223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4224 SILC_STATUS_ERR_NO_SERVER_ID);
4228 /* Send reply to the sender */
4229 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4232 /* Close the connection to the server */
4233 sock = (SilcSocketConnection)server_entry->connection;
4234 silc_server_free_sock_user_data(server, sock);
4235 silc_server_close_connection(server, sock);
4238 silc_server_command_free(cmd);
4241 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4242 active connections. */
4244 SILC_SERVER_CMD_FUNC(shutdown)
4246 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4247 SilcServer server = cmd->server;
4248 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4250 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4252 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4255 /* Check whether client has the permission. */
4256 if (client->mode == SILC_UMODE_NONE) {
4257 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4258 SILC_STATUS_ERR_NO_SERVER_PRIV);
4262 /* Send reply to the sender */
4263 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4266 /* Then, gracefully, or not, bring the server down. */
4267 silc_server_stop(server);
4271 silc_server_command_free(cmd);
4274 /* Server side command of LEAVE. Removes client from a channel. */
4276 SILC_SERVER_CMD_FUNC(leave)
4278 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4279 SilcServer server = cmd->server;
4280 SilcSocketConnection sock = cmd->sock;
4281 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4283 SilcChannelEntry channel;
4285 unsigned int i, len;
4288 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4290 /* Get Channel ID */
4291 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4294 SILC_STATUS_ERR_NO_CHANNEL_ID);
4297 id = silc_id_payload_parse_id(tmp, len);
4299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4300 SILC_STATUS_ERR_NO_CHANNEL_ID);
4304 /* Get channel entry */
4305 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4307 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4310 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4315 /* Check whether this client is on the channel */
4316 if (!silc_server_client_on_channel(id_entry, channel)) {
4317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4318 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4322 /* Notify routers that they should remove this client from their list
4323 of clients on the channel. Send LEAVE notify type. */
4324 if (!server->standalone)
4325 silc_server_send_notify_leave(server, server->router->connection,
4326 server->server_type == SILC_ROUTER ?
4327 TRUE : FALSE, channel, id_entry->id,
4328 SILC_ID_CLIENT_LEN);
4330 /* Remove client from channel */
4331 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4336 /* If the channel does not exist anymore we won't send anything */
4340 /* Re-generate channel key */
4341 silc_server_create_channel_key(server, channel, 0);
4343 /* Encode channel key payload to be distributed on the channel */
4345 silc_channel_key_payload_encode(len, tmp,
4346 strlen(channel->channel_key->cipher->name),
4347 channel->channel_key->cipher->name,
4348 channel->key_len / 8, channel->key);
4350 /* If we are normal server then we will send it to our router. If we
4351 are router we will send it to all local servers that has clients on
4353 if (server->server_type == SILC_SERVER) {
4354 if (!server->standalone)
4355 silc_server_packet_send(server,
4356 cmd->server->router->connection,
4357 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
4358 packet->len, FALSE);
4363 /* Send to locally connected clients on the channel */
4364 silc_server_packet_send_local_channel(server, channel,
4365 SILC_PACKET_CHANNEL_KEY, 0,
4366 packet->data, packet->len, FALSE);
4368 silc_buffer_free(packet);
4372 silc_server_command_free(cmd);
4375 /* Server side of command USERS. Resolves clients and their USERS currently
4376 joined on the requested channel. The list of Client ID's and their modes
4377 on the channel is sent back. */
4379 SILC_SERVER_CMD_FUNC(users)
4381 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4382 SilcServer server = cmd->server;
4383 SilcChannelEntry channel;
4386 unsigned char *channel_id;
4387 unsigned int channel_id_len;
4388 SilcBuffer client_id_list;
4389 SilcBuffer client_mode_list;
4390 unsigned char lc[4];
4391 unsigned int list_count = 0;
4392 unsigned short ident = silc_command_get_ident(cmd->payload);
4394 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4396 /* Get Channel ID */
4397 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4400 SILC_STATUS_ERR_NO_CHANNEL_ID);
4403 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4406 SILC_STATUS_ERR_NO_CHANNEL_ID);
4410 /* If we are server and we don't know about this channel we will send
4411 the command to our router. If we know about the channel then we also
4412 have the list of users already. */
4413 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4415 if (server->server_type == SILC_SERVER && !server->standalone &&
4419 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4420 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4422 /* Send USERS command */
4423 silc_server_packet_send(server, server->router->connection,
4424 SILC_PACKET_COMMAND, cmd->packet->flags,
4425 tmpbuf->data, tmpbuf->len, TRUE);
4427 /* Reprocess this packet after received reply */
4428 silc_server_command_pending(server, SILC_COMMAND_USERS,
4429 silc_command_get_ident(cmd->payload),
4430 silc_server_command_destructor,
4431 silc_server_command_users,
4432 silc_server_command_dup(cmd));
4433 cmd->pending = TRUE;
4434 silc_command_set_ident(cmd->payload, ident);
4436 silc_buffer_free(tmpbuf);
4441 /* We are router and we will check the global list as well. */
4442 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4444 /* Channel really does not exist */
4445 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4446 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4451 /* Get the users list */
4452 silc_server_get_users_on_channel(server, channel, &client_id_list,
4453 &client_mode_list, &list_count);
4456 SILC_PUT32_MSB(list_count, lc);
4459 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4460 SILC_STATUS_OK, ident, 4,
4461 2, channel_id, channel_id_len,
4463 4, client_id_list->data,
4464 client_id_list->len,
4465 5, client_mode_list->data,
4466 client_mode_list->len);
4467 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4468 packet->data, packet->len, FALSE);
4470 silc_buffer_free(packet);
4471 silc_buffer_free(client_id_list);
4472 silc_buffer_free(client_mode_list);
4476 silc_server_command_free(cmd);
4479 /* Server side of command BAN. This is used to manage the ban list of the
4480 channel. To add clients and remove clients from the ban list. */
4482 SILC_SERVER_CMD_FUNC(ban)
4484 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4485 SilcServer server = cmd->server;
4486 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4488 SilcChannelEntry channel;
4489 SilcChannelClientEntry chl;
4490 SilcChannelID *channel_id = NULL;
4491 unsigned char *id, *add, *del;
4492 unsigned int id_len, tmp_len;
4493 unsigned short ident = silc_command_get_ident(cmd->payload);
4495 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4498 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4500 /* Get Channel ID */
4501 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4503 channel_id = silc_id_payload_parse_id(id, id_len);
4505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4506 SILC_STATUS_ERR_NO_CHANNEL_ID);
4511 /* Get channel entry. The server must know about the channel since the
4512 client is expected to be on the channel. */
4513 channel = silc_idlist_find_channel_by_id(server->local_list,
4516 channel = silc_idlist_find_channel_by_id(server->global_list,
4519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4520 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4525 /* Check whether this client is on the channel */
4526 if (!silc_server_client_on_channel(client, channel)) {
4527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4528 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4532 /* Get entry to the channel user list */
4533 silc_list_start(channel->user_list);
4534 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4535 if (chl->client == client)
4538 /* The client must be at least channel operator. */
4539 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4541 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4545 /* Get the new ban and add it to the ban list */
4546 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4548 if (!channel->ban_list)
4549 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4551 channel->ban_list = silc_realloc(channel->ban_list,
4552 sizeof(*channel->ban_list) *
4554 strlen(channel->ban_list) + 2));
4555 if (add[tmp_len - 1] == ',')
4556 add[tmp_len - 1] = '\0';
4558 strncat(channel->ban_list, add, tmp_len);
4559 strncat(channel->ban_list, ",", 1);
4562 /* Get the ban to be removed and remove it from the list */
4563 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4564 if (del && channel->ban_list) {
4565 char *start, *end, *n;
4567 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4568 silc_free(channel->ban_list);
4569 channel->ban_list = NULL;
4571 start = strstr(channel->ban_list, del);
4572 if (start && strlen(start) >= tmp_len) {
4573 end = start + tmp_len;
4574 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4575 strncat(n, channel->ban_list, start - channel->ban_list);
4576 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4578 silc_free(channel->ban_list);
4579 channel->ban_list = n;
4584 /* Send the BAN notify type to our primary router. */
4585 if (!server->standalone && (add || del))
4586 silc_server_send_notify_ban(server, server->router->connection,
4587 server->server_type == SILC_ROUTER ?
4588 TRUE : FALSE, channel, add, del);
4590 /* Send the reply back to the client */
4591 if (channel->ban_list)
4593 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4594 SILC_STATUS_OK, ident, 2,
4596 3, channel->ban_list,
4597 strlen(channel->ban_list) - 1);
4600 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4601 SILC_STATUS_OK, ident, 1,
4604 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4605 packet->data, packet->len, FALSE);
4607 silc_buffer_free(packet);
4611 silc_free(channel_id);
4612 silc_server_command_free(cmd);