5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 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,
35 silc_server_command_send_status_data(SilcServerCommandContext cmd,
40 const unsigned char *arg,
43 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
44 SilcServerCommandReplyContext cmdr,
46 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
48 /* Server command list. */
49 SilcServerCommand silc_command_list[] =
51 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
54 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
55 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
56 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
60 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
64 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
65 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
68 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
69 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
71 SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
72 SILC_SERVER_CMD(watch, WATCH, SILC_CF_LAG | SILC_CF_REG),
73 SILC_SERVER_CMD(silcoper, SILCOPER,
74 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
75 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
76 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
77 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
79 SILC_SERVER_CMD(connect, PRIV_CONNECT,
80 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
81 SILC_SERVER_CMD(close, PRIV_CLOSE,
82 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
83 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
89 /* Performs several checks to the command. It first checks whether this
90 command was called as pending command callback. If it was then it checks
91 whether error occurred in the command reply where the pending command
94 It also checks that the requested command includes correct amount
96 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
100 SILC_LOG_DEBUG(("Start")); \
102 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
103 silc_server_command_free(cmd); \
107 _argc = silc_argument_get_arg_num(cmd->args); \
109 silc_server_command_send_status_reply(cmd, command, \
110 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, \
112 silc_server_command_free(cmd); \
116 silc_server_command_send_status_reply(cmd, command, \
117 SILC_STATUS_ERR_TOO_MANY_PARAMS, \
119 silc_server_command_free(cmd); \
124 /* Returns TRUE if the connection is registered. Unregistered connections
125 usually cannot send commands hence the check. */
127 static int silc_server_is_registered(SilcServer server,
128 SilcSocketConnection sock,
129 SilcServerCommandContext cmd,
132 SilcIDListData idata = (SilcIDListData)sock->user_data;
137 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
140 silc_server_command_send_status_reply(cmd, command,
141 SILC_STATUS_ERR_NOT_REGISTERED, 0);
145 /* Internal context to hold data when executed command with timeout. */
147 SilcServerCommandContext ctx;
148 SilcServerCommand *cmd;
149 } *SilcServerCommandTimeout;
151 /* Timeout callback to process commands with timeout for client. Client's
152 commands are always executed with timeout. */
154 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
156 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
157 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
160 silc_server_command_free(timeout->ctx);
164 /* Update access time */
165 client->last_command = time(NULL);
167 if (!(timeout->cmd->flags & SILC_CF_REG))
168 timeout->cmd->cb(timeout->ctx, NULL);
169 else if (silc_server_is_registered(timeout->ctx->server,
173 timeout->cmd->cb(timeout->ctx, NULL);
175 silc_server_command_free(timeout->ctx);
180 /* Processes received command packet. */
182 void silc_server_command_process(SilcServer server,
183 SilcSocketConnection sock,
184 SilcPacketContext *packet)
186 SilcServerCommandContext ctx;
187 SilcServerCommand *cmd;
190 /* Allocate command context. This must be free'd by the
191 command routine receiving it. */
192 ctx = silc_server_command_alloc();
193 ctx->server = server;
194 ctx->sock = silc_socket_dup(sock);
195 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
197 /* Parse the command payload in the packet */
198 ctx->payload = silc_command_payload_parse(packet->buffer->data,
199 packet->buffer->len);
201 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
202 silc_buffer_free(packet->buffer);
203 silc_packet_context_free(packet);
204 silc_socket_free(ctx->sock);
208 ctx->args = silc_command_get_args(ctx->payload);
210 /* Get the command */
211 command = silc_command_get(ctx->payload);
212 for (cmd = silc_command_list; cmd->cb; cmd++)
213 if (cmd->cmd == command)
216 if (!cmd || !cmd->cb) {
217 silc_server_command_send_status_reply(ctx, command,
218 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
219 silc_server_command_free(ctx);
223 /* Execute client's commands always with timeout. Normally they are
224 executed with zero (0) timeout but if client is sending command more
225 frequently than once in 2 seconds, then the timeout may be 0 to 2
227 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
228 SilcClientEntry client = (SilcClientEntry)sock->user_data;
229 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
235 if (client->last_command && (time(NULL) - client->last_command) < 2) {
236 client->fast_command++;
239 if (client->fast_command - 2 <= 0)
240 client->fast_command = 0;
242 client->fast_command -= 2;
246 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
247 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
248 silc_schedule_task_add(server->schedule, sock->sock,
249 silc_server_command_process_timeout, timeout,
250 (client->fast_command < 3 ? 0 :
251 2 - (time(NULL) - client->last_command)),
252 (client->fast_command < 3 ? 200000 : 0),
253 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
255 silc_schedule_task_add(server->schedule, sock->sock,
256 silc_server_command_process_timeout, timeout,
257 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
261 /* Execute for server */
263 if (!(cmd->flags & SILC_CF_REG))
265 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
268 silc_server_command_free(ctx);
271 /* Allocate Command Context */
273 SilcServerCommandContext silc_server_command_alloc()
275 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
280 /* Free's the command context allocated before executing the command */
282 void silc_server_command_free(SilcServerCommandContext ctx)
285 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
287 if (ctx->users < 1) {
289 silc_command_payload_free(ctx->payload);
291 silc_packet_context_free(ctx->packet);
293 silc_socket_free(ctx->sock); /* Decrease reference counter */
298 /* Duplicate Command Context by adding reference counter. The context won't
299 be free'd untill it hits zero. */
301 SilcServerCommandContext
302 silc_server_command_dup(SilcServerCommandContext ctx)
305 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
310 /* Add new pending command to be executed when reply to a command has been
311 received. The `reply_cmd' is the command that will call the `callback'
312 with `context' when reply has been received. It can be SILC_COMMAND_NONE
313 to match any command with the `ident'. If `ident' is non-zero
314 the `callback' will be executed when received reply with command
315 identifier `ident'. If there already exists pending command for the
316 specified command, ident, callback and context this function has no
319 bool silc_server_command_pending(SilcServer server,
320 SilcCommand reply_cmd,
322 SilcCommandCb callback,
325 SilcServerCommandPending *reply;
327 /* Check whether identical pending already exists for same command,
328 ident, callback and callback context. If it does then it would be
329 error to register it again. */
330 silc_dlist_start(server->pending_commands);
331 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
332 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
333 reply->callback == callback && reply->context == context)
337 reply = silc_calloc(1, sizeof(*reply));
338 reply->reply_cmd = reply_cmd;
339 reply->ident = ident;
340 reply->context = context;
341 reply->callback = callback;
342 silc_dlist_add(server->pending_commands, reply);
347 /* Deletes pending command by reply command type. */
349 void silc_server_command_pending_del(SilcServer server,
350 SilcCommand reply_cmd,
353 SilcServerCommandPending *r;
355 silc_dlist_start(server->pending_commands);
356 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
357 if (r->reply_cmd == reply_cmd && r->ident == ident) {
358 silc_dlist_del(server->pending_commands, r);
364 /* Checks for pending commands and marks callbacks to be called from
365 the command reply function. Returns TRUE if there were pending command. */
367 SilcServerCommandPendingCallbacks
368 silc_server_command_pending_check(SilcServer server,
369 SilcServerCommandReplyContext ctx,
372 SilcUInt32 *callbacks_count)
374 SilcServerCommandPending *r;
375 SilcServerCommandPendingCallbacks callbacks = NULL;
378 silc_dlist_start(server->pending_commands);
379 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
380 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
381 && r->ident == ident) {
382 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
383 callbacks[i].context = r->context;
384 callbacks[i].callback = r->callback;
390 *callbacks_count = i;
394 /* Sends simple status message as command reply packet */
397 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
404 SILC_LOG_DEBUG(("Sending command status %d", status));
407 silc_command_reply_payload_encode_va(command, status, error,
408 silc_command_get_ident(cmd->payload),
410 silc_server_packet_send(cmd->server, cmd->sock,
411 SILC_PACKET_COMMAND_REPLY, 0,
412 buffer->data, buffer->len, FALSE);
413 silc_buffer_free(buffer);
416 /* Sends command status reply with one extra argument. The argument
417 type must be sent as argument. */
420 silc_server_command_send_status_data(SilcServerCommandContext cmd,
425 const unsigned char *arg,
430 SILC_LOG_DEBUG(("Sending command status %d", status));
433 silc_command_reply_payload_encode_va(command, status, 0,
434 silc_command_get_ident(cmd->payload),
435 1, arg_type, arg, arg_len);
436 silc_server_packet_send(cmd->server, cmd->sock,
437 SILC_PACKET_COMMAND_REPLY, 0,
438 buffer->data, buffer->len, FALSE);
439 silc_buffer_free(buffer);
442 /* This function can be called to check whether in the command reply
443 an error occurred. This function has no effect if this is called
444 when the command function was not called as pending command callback.
445 This returns TRUE if error had occurred. */
448 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
449 SilcServerCommandReplyContext cmdr,
452 if (!cmd->pending || !cmdr)
455 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
458 /* Send the same command reply payload */
459 silc_command_set_ident(cmdr->payload,
460 silc_command_get_ident(cmd->payload));
461 buffer = silc_command_payload_encode_payload(cmdr->payload);
462 silc_server_packet_send(cmd->server, cmd->sock,
463 SILC_PACKET_COMMAND_REPLY, 0,
464 buffer->data, buffer->len, FALSE);
465 silc_buffer_free(buffer);
472 /******************************************************************************
476 ******************************************************************************/
484 #define ADD_ERROR(errptr, errptr_count, _id, _index, _status) \
486 errptr = silc_realloc(errptr, sizeof(*errptr) * (errptr_count + 1)); \
489 errptr[errptr_count].id = _id; \
490 errptr[errptr_count].index = _index; \
491 errptr[errptr_count].error = _status; \
496 silc_server_command_whois_parse(SilcServerCommandContext cmd,
497 SilcClientID ***client_id,
498 SilcUInt32 *client_id_count,
502 ResolveError *error_client,
503 SilcUInt32 *error_client_count)
507 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
511 /* If client ID is in the command it must be used instead of nickname */
512 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
514 /* No ID, get the nickname@server string and parse it. */
515 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
517 silc_parse_userfqdn(tmp, nickname, server_name);
519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
520 SILC_STATUS_ERR_BAD_NICKNAME, 0);
524 /* Command includes ID, we must use that. Take all ID's from the
526 for (k = 0, i = 0; i < argc; i++) {
527 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
530 id = silc_id_payload_parse_id(tmp, len, NULL);
532 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
533 (*client_id_count + 1));
534 (*client_id)[k] = id;
535 (*client_id_count)++;
538 ADD_ERROR((*error_client), (*error_client_count), NULL, i + 3,
539 SILC_STATUS_ERR_BAD_CLIENT_ID);
544 /* Get the max count of reply messages allowed */
545 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
547 SILC_GET32_MSB(*count, tmp);
555 /* Resolve context used by both WHOIS and IDENTIFY commands */
557 SilcServerEntry router;
559 unsigned char **res_argv;
560 SilcUInt32 *res_argv_lens;
561 SilcUInt32 *res_argv_types;
563 } *SilcServerResolveContext;
566 silc_server_command_whois_check(SilcServerCommandContext cmd,
567 SilcClientEntry *clients,
568 SilcUInt32 clients_count)
570 SilcServer server = cmd->server;
571 SilcClientEntry entry;
572 SilcServerResolveContext resolve = NULL, r = NULL;
573 SilcUInt32 resolve_count = 0;
577 SILC_LOG_DEBUG(("Start"));
579 for (i = 0; i < clients_count; i++) {
584 if ((entry->nickname && entry->username && entry->userinfo) ||
585 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
589 /* If we are normal server, and we've not resolved this client from
590 router and it is global client, we'll check whether it is on some
591 channel. If not then we cannot be sure about its validity, and
592 we'll resolve it from router. */
593 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
594 entry->connection || silc_hash_table_count(entry->channels))
598 /* We need to resolve this entry since it is not complete */
600 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
601 /* The entry is being resolved (and we are not the resolver) so attach
602 to the command reply and we're done with this one. */
603 silc_server_command_pending(server, SILC_COMMAND_NONE,
604 entry->resolve_cmd_ident,
605 silc_server_command_whois,
606 silc_server_command_dup(cmd));
609 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
610 /* We've resolved this and it still is not ready. We'll return
611 and are that this will be handled again after it is resolved. */
612 for (i = 0; i < resolve_count; i++) {
613 for (k = 0; k < r->res_argc; k++)
614 silc_free(r->res_argv[k]);
615 silc_free(r->res_argv);
616 silc_free(r->res_argv_lens);
617 silc_free(r->res_argv_types);
622 /* We'll resolve this client */
626 for (k = 0; k < resolve_count; k++) {
627 if (resolve[k].router == entry->router) {
634 resolve = silc_realloc(resolve, sizeof(*resolve) *
635 (resolve_count + 1));
636 r = &resolve[resolve_count];
637 memset(r, 0, sizeof(*r));
638 r->router = entry->router;
639 r->ident = ++server->cmd_ident;
643 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
645 r->res_argv_lens = silc_realloc(r->res_argv_lens,
646 sizeof(*r->res_argv_lens) *
648 r->res_argv_types = silc_realloc(r->res_argv_types,
649 sizeof(*r->res_argv_types) *
651 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
652 r->res_argv[r->res_argc] = silc_calloc(idp->len,
653 sizeof(**r->res_argv));
654 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
655 r->res_argv_lens[r->res_argc] = idp->len;
656 r->res_argv_types[r->res_argc] = r->res_argc + 3;
658 silc_buffer_free(idp);
660 entry->resolve_cmd_ident = r->ident;
661 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
662 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
667 /* Do the resolving */
668 for (i = 0; i < resolve_count; i++) {
673 /* Send WHOIS request. We send WHOIS since we're doing the requesting
674 now anyway so make it a good one. */
675 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
676 r->res_argc, r->res_argv,
680 silc_server_packet_send(server, r->router->connection,
681 SILC_PACKET_COMMAND, cmd->packet->flags,
682 res_cmd->data, res_cmd->len, FALSE);
684 /* Reprocess this packet after received reply */
685 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
687 silc_server_command_whois,
688 silc_server_command_dup(cmd));
691 silc_buffer_free(res_cmd);
692 for (k = 0; k < r->res_argc; k++)
693 silc_free(r->res_argv[k]);
694 silc_free(r->res_argv);
695 silc_free(r->res_argv_lens);
696 silc_free(r->res_argv_types);
705 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
706 SilcClientEntry *clients,
707 SilcUInt32 clients_count,
709 SilcUInt32 errors_count,
710 int count, const char *nickname,
711 SilcClientID **client_ids)
713 SilcServer server = cmd->server;
715 int i, k, valid_count = clients_count;
717 SilcBuffer packet, idp, channels, umode_list = NULL;
718 SilcClientEntry entry;
720 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
721 char nh[256], uh[256];
722 unsigned char idle[4], mode[4];
723 unsigned char *fingerprint;
724 SilcSocketConnection hsock;
727 /* Process only valid clients and ignore those that are not registered.
728 This is checked with nickname only because when resolved client IDs
729 we check that they are registered earlier. */
731 for (i = 0; i < clients_count; i++)
732 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
738 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
739 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
740 3, nickname, strlen(nickname));
745 /* Start processing found clients. */
746 status = SILC_STATUS_OK;
748 status = SILC_STATUS_LIST_START;
750 for (i = 0, k = 0; i < clients_count; i++) {
756 status = SILC_STATUS_LIST_ITEM;
757 if (valid_count > 1 && k == valid_count - 1 && !errors_count)
758 status = SILC_STATUS_LIST_END;
759 if (count && k - 1 == count)
760 status = SILC_STATUS_LIST_END;
762 /* Send WHOIS reply */
763 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
764 tmp = silc_argument_get_first_arg(cmd->args, NULL);
766 memset(uh, 0, sizeof(uh));
767 memset(nh, 0, sizeof(nh));
768 memset(idle, 0, sizeof(idle));
770 strncat(nh, entry->nickname, strlen(entry->nickname));
771 if (!strchr(entry->nickname, '@')) {
773 if (entry->servername) {
774 strncat(nh, entry->servername, strlen(entry->servername));
776 len = entry->router ? strlen(entry->router->server_name) :
777 strlen(server->server_name);
778 strncat(nh, entry->router ? entry->router->server_name :
779 server->server_name, len);
783 strncat(uh, entry->username, strlen(entry->username));
784 if (!strchr(entry->username, '@') && entry->connection) {
786 hsock = (SilcSocketConnection)entry->connection;
787 len = strlen(hsock->hostname);
788 strncat(uh, hsock->hostname, len);
791 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
792 channels = silc_server_get_client_channel_list(server, entry, FALSE,
795 channels = silc_server_get_client_channel_list(server, entry, TRUE,
798 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
799 fingerprint = entry->data.fingerprint;
803 SILC_PUT32_MSB(entry->mode, mode);
804 if (entry->connection)
805 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
808 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
810 2, idp->data, idp->len,
814 strlen(entry->userinfo),
815 6, channels ? channels->data : NULL,
816 channels ? channels->len : 0,
820 fingerprint ? 20 : 0,
821 10, umode_list ? umode_list->data :
822 NULL, umode_list ? umode_list->len :
825 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
826 0, packet->data, packet->len, FALSE);
828 silc_buffer_free(packet);
829 silc_buffer_free(idp);
831 silc_buffer_free(channels);
833 silc_buffer_free(umode_list);
837 if (count && k - 1 == count)
842 /* Send error replies */
843 if (status == SILC_STATUS_OK && errors_count > 1)
844 status = SILC_STATUS_LIST_START;
847 for (i = 0, k = 0; i < errors_count; i++) {
849 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
853 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
857 status = SILC_STATUS_LIST_ITEM;
858 if (errors_count > 1 && k == errors_count - 1)
859 status = SILC_STATUS_LIST_END;
860 if (count && k - 1 == count)
861 status = SILC_STATUS_LIST_END;
864 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
865 (status == SILC_STATUS_OK ?
866 errors[i].error : status),
867 (status == SILC_STATUS_OK ?
868 0 : errors[i].error),
870 silc_buffer_free(idp);
873 if (count && k - 1 == count)
880 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
882 SilcServer server = cmd->server;
884 SilcUInt16 old_ident;
886 old_ident = silc_command_get_ident(cmd->payload);
887 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
888 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
890 /* Send WHOIS command to our router */
891 silc_server_packet_send(server, (SilcSocketConnection)
892 server->router->connection,
893 SILC_PACKET_COMMAND, cmd->packet->flags,
894 tmpbuf->data, tmpbuf->len, TRUE);
896 /* Reprocess this packet after received reply from router */
897 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
898 silc_command_get_ident(cmd->payload),
899 silc_server_command_whois,
900 silc_server_command_dup(cmd));
902 silc_command_set_ident(cmd->payload, old_ident);
903 silc_buffer_free(tmpbuf);
907 silc_server_command_whois_process(SilcServerCommandContext cmd)
909 SilcServer server = cmd->server;
910 char *nick = NULL, *server_name = NULL;
912 SilcClientEntry *clients = NULL, entry;
913 SilcClientID **client_id = NULL;
914 SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
915 ResolveError error_client = NULL;
917 bool check_global = FALSE;
919 /* Parse the whois request */
920 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
921 &nick, &server_name, &count,
922 &error_client, &error_client_count))
925 /* Send the WHOIS request to the router only if it included nickname.
926 Since nicknames can be expanded into many clients we need to send it
927 to router. If the WHOIS included only client ID's we will check them
928 first locally since we just might have them. */
929 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
930 server->server_type == SILC_SERVER && !cmd->pending &&
931 !server->standalone) {
932 silc_server_command_whois_send_router(cmd);
937 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
939 else if (server->server_type != SILC_SERVER)
942 /* Get all clients matching that ID or nickname from local list */
943 if (client_id_count) {
944 /* Check all Client ID's received in the command packet */
945 for (i = 0; i < client_id_count; i++) {
946 entry = silc_idlist_find_client_by_id(server->local_list,
947 client_id[i], TRUE, NULL);
948 if (!entry && check_global)
949 entry = silc_idlist_find_client_by_id(server->global_list,
950 client_id[i], TRUE, NULL);
952 clients = silc_realloc(clients, sizeof(*clients) *
953 (clients_count + 1));
954 clients[clients_count++] = entry;
956 /* If we are normal server and did not send the request first to router
957 do it now, since we do not have the Client ID information. */
958 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
959 server->server_type == SILC_SERVER && !cmd->pending &&
960 !server->standalone) {
961 silc_server_command_whois_send_router(cmd);
966 ADD_ERROR(error_client, error_client_count, client_id[i], 0,
967 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
971 /* Find by nickname */
972 if (!silc_idlist_get_clients_by_hash(server->local_list,
973 nick, server->md5hash,
974 &clients, &clients_count))
975 silc_idlist_get_clients_by_nickname(server->local_list,
977 &clients, &clients_count);
979 if (!silc_idlist_get_clients_by_hash(server->global_list,
980 nick, server->md5hash,
981 &clients, &clients_count))
982 silc_idlist_get_clients_by_nickname(server->global_list,
984 &clients, &clients_count);
988 if (!clients && (client_id_count || nick)) {
989 /* If we are normal server and did not send the request first to router
990 do it now, since we do not have the information. */
991 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
992 server->server_type == SILC_SERVER && !cmd->pending &&
993 !server->standalone) {
994 silc_server_command_whois_send_router(cmd);
999 /* Such client(s) really does not exist in the SILC network. */
1000 if (!client_id_count)
1001 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1002 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1003 3, nick, strlen(nick));
1005 silc_server_command_whois_send_reply(cmd, NULL, 0,
1006 error_client, error_client_count,
1011 /* Router always finds the client entry if it exists in the SILC network.
1012 However, it might be incomplete entry and does not include all the
1013 mandatory fields that WHOIS command reply requires. Check for these and
1014 make query from the server who owns the client if some fields are
1016 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
1021 /* Send the command reply */
1022 silc_server_command_whois_send_reply(cmd, clients, clients_count,
1023 error_client, error_client_count,
1024 count, nick, client_id);
1027 if (client_id_count) {
1028 for (i = 0; i < client_id_count; i++)
1029 silc_free(client_id[i]);
1030 silc_free(client_id);
1033 silc_free(error_client);
1035 silc_free(server_name);
1040 /* Server side of command WHOIS. Processes user's query and sends found
1041 results as command replies back to the client. */
1043 SILC_SERVER_CMD_FUNC(whois)
1045 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1048 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1050 ret = silc_server_command_whois_process(cmd);
1051 silc_server_command_free(cmd);
1054 /******************************************************************************
1058 ******************************************************************************/
1061 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1069 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1071 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1072 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1077 /* Get the nickname@server string and parse it. */
1078 silc_parse_userfqdn(tmp, nickname, server_name);
1080 /* Get the max count of reply messages allowed */
1081 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1083 SILC_GET32_MSB(*count, tmp);
1092 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1093 SilcClientEntry *clients,
1094 SilcUInt32 clients_count)
1096 SilcServer server = cmd->server;
1098 SilcClientEntry entry;
1100 for (i = 0; i < clients_count; i++) {
1103 if (!entry->nickname || !entry->username) {
1105 SilcUInt16 old_ident;
1110 old_ident = silc_command_get_ident(cmd->payload);
1111 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1112 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1114 /* Send WHOWAS command */
1115 silc_server_packet_send(server, entry->router->connection,
1116 SILC_PACKET_COMMAND, cmd->packet->flags,
1117 tmpbuf->data, tmpbuf->len, TRUE);
1119 /* Reprocess this packet after received reply */
1120 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1121 silc_command_get_ident(cmd->payload),
1122 silc_server_command_whowas,
1123 silc_server_command_dup(cmd));
1124 cmd->pending = TRUE;
1125 silc_command_set_ident(cmd->payload, old_ident);
1127 silc_buffer_free(tmpbuf);
1136 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1137 SilcClientEntry *clients,
1138 SilcUInt32 clients_count)
1140 SilcServer server = cmd->server;
1142 int i, k, count = 0, len;
1143 SilcBuffer packet, idp;
1144 SilcClientEntry entry = NULL;
1146 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1147 char nh[256], uh[256];
1150 status = SILC_STATUS_OK;
1152 /* Process only entries that are not registered anymore. */
1154 for (i = 0; i < clients_count; i++) {
1155 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1162 /* No valid entries found at all, just send error */
1165 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1167 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1168 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1169 3, tmp, strlen(tmp));
1173 if (valid_count > 1)
1174 status = SILC_STATUS_LIST_START;
1176 for (i = 0, k = 0; i < clients_count; i++) {
1182 status = SILC_STATUS_LIST_ITEM;
1183 if (valid_count > 1 && k == valid_count - 1)
1184 status = SILC_STATUS_LIST_END;
1185 if (count && k - 1 == count)
1186 status = SILC_STATUS_LIST_END;
1187 if (count && k - 1 > count)
1190 /* Send WHOWAS reply */
1191 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1192 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1193 memset(uh, 0, sizeof(uh));
1194 memset(nh, 0, sizeof(nh));
1196 strncat(nh, entry->nickname, strlen(entry->nickname));
1197 if (!strchr(entry->nickname, '@')) {
1198 strncat(nh, "@", 1);
1199 if (entry->servername) {
1200 strncat(nh, entry->servername, strlen(entry->servername));
1202 len = entry->router ? strlen(entry->router->server_name) :
1203 strlen(server->server_name);
1204 strncat(nh, entry->router ? entry->router->server_name :
1205 server->server_name, len);
1209 strncat(uh, entry->username, strlen(entry->username));
1210 if (!strchr(entry->username, '@')) {
1211 strncat(uh, "@", 1);
1212 strcat(uh, "*private*");
1216 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1217 status, 0, ident, 4,
1218 2, idp->data, idp->len,
1223 strlen(entry->userinfo) : 0);
1224 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1225 0, packet->data, packet->len, FALSE);
1227 silc_buffer_free(packet);
1228 silc_buffer_free(idp);
1235 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1237 SilcServer server = cmd->server;
1238 char *nick = NULL, *server_name = NULL;
1240 SilcClientEntry *clients = NULL;
1241 SilcUInt32 clients_count = 0;
1243 bool check_global = FALSE;
1245 /* Protocol dictates that we must always send the received WHOWAS request
1246 to our router if we are normal server, so let's do it now unless we
1247 are standalone. We will not send any replies to the client until we
1248 have received reply from the router. */
1249 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1250 server->server_type == SILC_SERVER && !cmd->pending &&
1251 !server->standalone) {
1253 SilcUInt16 old_ident;
1255 old_ident = silc_command_get_ident(cmd->payload);
1256 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1257 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1259 /* Send WHOWAS command to our router */
1260 silc_server_packet_send(server, (SilcSocketConnection)
1261 server->router->connection,
1262 SILC_PACKET_COMMAND, cmd->packet->flags,
1263 tmpbuf->data, tmpbuf->len, TRUE);
1265 /* Reprocess this packet after received reply from router */
1266 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1267 silc_command_get_ident(cmd->payload),
1268 silc_server_command_whowas,
1269 silc_server_command_dup(cmd));
1270 cmd->pending = TRUE;
1271 silc_command_set_ident(cmd->payload, old_ident);
1273 silc_buffer_free(tmpbuf);
1278 /* We are ready to process the command request. Let's search for the
1279 requested client and send reply to the requesting client. */
1281 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1282 check_global = TRUE;
1283 else if (server->server_type != SILC_SERVER)
1284 check_global = TRUE;
1286 /* Parse the whowas request */
1287 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1290 /* Get all clients matching that nickname from local list */
1291 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1293 &clients, &clients_count))
1294 silc_idlist_get_clients_by_hash(server->local_list,
1295 nick, server->md5hash,
1296 &clients, &clients_count);
1298 /* Check global list as well */
1300 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1302 &clients, &clients_count))
1303 silc_idlist_get_clients_by_hash(server->global_list,
1304 nick, server->md5hash,
1305 &clients, &clients_count);
1309 /* Such a client really does not exist in the SILC network. */
1310 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1311 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1312 3, nick, strlen(nick));
1316 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1321 /* Send the command reply to the client */
1322 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1327 silc_free(server_name);
1331 /* Server side of command WHOWAS. */
1333 SILC_SERVER_CMD_FUNC(whowas)
1335 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1338 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1340 ret = silc_server_command_whowas_process(cmd);
1341 silc_server_command_free(cmd);
1344 /******************************************************************************
1348 ******************************************************************************/
1351 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1353 SilcServer server = cmd->server;
1355 SilcUInt16 old_ident;
1357 old_ident = silc_command_get_ident(cmd->payload);
1358 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1359 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1361 /* Send IDENTIFY command to our router */
1362 silc_server_packet_send(server, (SilcSocketConnection)
1363 server->router->connection,
1364 SILC_PACKET_COMMAND, cmd->packet->flags,
1365 tmpbuf->data, tmpbuf->len, TRUE);
1367 /* Reprocess this packet after received reply from router */
1368 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1369 silc_command_get_ident(cmd->payload),
1370 silc_server_command_identify,
1371 silc_server_command_dup(cmd));
1372 cmd->pending = TRUE;
1373 silc_command_set_ident(cmd->payload, old_ident);
1374 silc_buffer_free(tmpbuf);
1378 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1379 SilcClientEntry **clients,
1380 SilcUInt32 *clients_count,
1381 SilcServerEntry **servers,
1382 SilcUInt32 *servers_count,
1383 SilcChannelEntry **channels,
1384 SilcUInt32 *channels_count,
1387 SilcServer server = cmd->server;
1390 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1392 bool check_global = FALSE;
1397 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1398 check_global = TRUE;
1399 else if (server->server_type != SILC_SERVER)
1400 check_global = TRUE;
1402 /* If ID Payload is in the command it must be used instead of names */
1403 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1405 /* No ID, get the names. */
1407 /* If we are normal server and have not resolved information from
1408 router yet, do so now. */
1409 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1410 server->server_type == SILC_SERVER && !cmd->pending &&
1411 !server->standalone) {
1412 silc_server_command_identify_send_router(cmd);
1416 /* Try to get nickname@server. */
1417 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1420 char *nick_server = NULL;
1422 silc_parse_userfqdn(tmp, &nick, &nick_server);
1424 if (!silc_idlist_get_clients_by_hash(server->local_list,
1425 nick, server->md5hash,
1426 clients, clients_count))
1427 silc_idlist_get_clients_by_nickname(server->local_list,
1429 clients, clients_count);
1431 if (!silc_idlist_get_clients_by_hash(server->global_list,
1432 nick, server->md5hash,
1433 clients, clients_count))
1434 silc_idlist_get_clients_by_nickname(server->global_list,
1436 clients, clients_count);
1440 silc_free(nick_server);
1443 /* the nickname does not exist, send error reply */
1444 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1445 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1446 3, tmp, strlen(tmp));
1451 /* Try to get server name */
1452 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1454 entry = silc_idlist_find_server_by_name(server->local_list,
1456 if (!entry && check_global)
1457 entry = silc_idlist_find_server_by_name(server->global_list,
1460 *servers = silc_realloc(*servers, sizeof(**servers) *
1461 (*servers_count + 1));
1462 (*servers)[(*servers_count)++] = entry;
1466 /* the server does not exist, send error reply */
1467 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1468 SILC_STATUS_ERR_NO_SUCH_SERVER,
1469 0, 3, tmp, strlen(tmp));
1474 /* Try to get channel name */
1475 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1477 entry = silc_idlist_find_channel_by_name(server->local_list,
1479 if (!entry && check_global)
1480 entry = silc_idlist_find_channel_by_name(server->global_list,
1483 *channels = silc_realloc(*channels, sizeof(**channels) *
1484 (*channels_count + 1));
1485 (*channels)[(*channels_count)++] = entry;
1489 /* The channel does not exist, send error reply */
1490 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1491 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1492 0, 3, tmp, strlen(tmp));
1497 if (!(*clients) && !(*servers) && !(*channels)) {
1498 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1499 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1504 /* Command includes ID, we must use that. Also check whether the command
1505 has more than one ID set - take them all. */
1507 /* Take all ID's from the command packet */
1508 for (i = 0; i < argc; i++) {
1511 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1515 idp = silc_id_payload_parse(tmp, len);
1517 silc_free(*clients);
1518 silc_free(*servers);
1519 silc_free(*channels);
1520 silc_server_command_send_status_reply(
1521 cmd, SILC_COMMAND_IDENTIFY,
1522 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
1526 id = silc_id_payload_get_id(idp);
1528 switch (silc_id_payload_get_type(idp)) {
1530 case SILC_ID_CLIENT:
1531 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1533 if (!entry && check_global)
1534 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1537 *clients = silc_realloc(*clients, sizeof(**clients) *
1538 (*clients_count + 1));
1539 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1541 /* If we are normal server and have not resolved information from
1542 router yet, do so now. */
1543 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1544 server->server_type == SILC_SERVER && !cmd->pending &&
1545 !server->standalone) {
1546 silc_server_command_identify_send_router(cmd);
1547 silc_free(*clients);
1548 silc_free(*servers);
1549 silc_free(*channels);
1552 silc_server_command_send_status_data(
1553 cmd, SILC_COMMAND_IDENTIFY,
1554 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1562 case SILC_ID_SERVER:
1563 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1565 if (!entry && check_global)
1566 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1569 *servers = silc_realloc(*servers, sizeof(**servers) *
1570 (*servers_count + 1));
1571 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1573 /* If we are normal server and have not resolved information from
1574 router yet, do so now. */
1575 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1576 server->server_type == SILC_SERVER && !cmd->pending &&
1577 !server->standalone) {
1578 silc_server_command_identify_send_router(cmd);
1579 silc_free(*clients);
1580 silc_free(*servers);
1581 silc_free(*channels);
1584 silc_server_command_send_status_data(
1585 cmd, SILC_COMMAND_IDENTIFY,
1586 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1593 case SILC_ID_CHANNEL:
1594 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1596 if (!entry && check_global)
1597 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1600 *channels = silc_realloc(*channels, sizeof(**channels) *
1601 (*channels_count + 1));
1602 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1604 /* If we are normal server and have not resolved information from
1605 router yet, do so now. */
1606 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1607 server->server_type == SILC_SERVER && !cmd->pending &&
1608 !server->standalone) {
1609 silc_server_command_identify_send_router(cmd);
1610 silc_free(*clients);
1611 silc_free(*servers);
1612 silc_free(*channels);
1615 silc_server_command_send_status_data(
1616 cmd, SILC_COMMAND_IDENTIFY,
1617 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1630 silc_free(*clients);
1631 silc_free(*servers);
1632 silc_free(*channels);
1636 /* Get the max count of reply messages allowed */
1637 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1639 SILC_GET32_MSB(*count, tmp);
1647 /* Checks that all mandatory fields in client entry are present. If not
1648 then send WHOIS request to the server who owns the client. We use
1649 WHOIS because we want to get as much information as possible at once. */
1652 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1653 SilcClientEntry *clients,
1654 SilcUInt32 clients_count)
1656 SilcServer server = cmd->server;
1657 SilcClientEntry entry;
1658 SilcServerResolveContext resolve = NULL, r = NULL;
1659 SilcUInt32 resolve_count = 0;
1663 for (i = 0; i < clients_count; i++) {
1668 if (entry->nickname ||
1669 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1673 /* If we are normal server, and we've not resolved this client from
1674 router and it is global client, we'll check whether it is on some
1675 channel. If not then we cannot be sure about its validity, and
1676 we'll resolve it from router. */
1677 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1678 entry->connection || silc_hash_table_count(entry->channels))
1682 /* We need to resolve this entry since it is not complete */
1684 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1685 /* The entry is being resolved (and we are not the resolver) so attach
1686 to the command reply and we're done with this one. */
1687 silc_server_command_pending(server, SILC_COMMAND_NONE,
1688 entry->resolve_cmd_ident,
1689 silc_server_command_identify,
1690 silc_server_command_dup(cmd));
1693 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1694 /* We've resolved this and it still is not ready. We'll return
1695 and are that this will be handled again after it is resolved. */
1696 for (i = 0; i < resolve_count; i++) {
1697 for (k = 0; k < r->res_argc; k++)
1698 silc_free(r->res_argv[k]);
1699 silc_free(r->res_argv);
1700 silc_free(r->res_argv_lens);
1701 silc_free(r->res_argv_types);
1706 /* We'll resolve this client */
1710 for (k = 0; k < resolve_count; k++) {
1711 if (resolve[k].router == entry->router) {
1718 resolve = silc_realloc(resolve, sizeof(*resolve) *
1719 (resolve_count + 1));
1720 r = &resolve[resolve_count];
1721 memset(r, 0, sizeof(*r));
1722 r->router = entry->router;
1723 r->ident = ++server->cmd_ident;
1727 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1729 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1730 sizeof(*r->res_argv_lens) *
1732 r->res_argv_types = silc_realloc(r->res_argv_types,
1733 sizeof(*r->res_argv_types) *
1735 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1736 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1737 sizeof(**r->res_argv));
1738 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1739 r->res_argv_lens[r->res_argc] = idp->len;
1740 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1742 silc_buffer_free(idp);
1744 entry->resolve_cmd_ident = r->ident;
1745 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1746 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1751 /* Do the resolving */
1752 for (i = 0; i < resolve_count; i++) {
1757 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1758 now anyway so make it a good one. */
1759 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1760 r->res_argc, r->res_argv,
1764 silc_server_packet_send(server, r->router->connection,
1765 SILC_PACKET_COMMAND, cmd->packet->flags,
1766 res_cmd->data, res_cmd->len, FALSE);
1768 /* Reprocess this packet after received reply */
1769 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1771 silc_server_command_identify,
1772 silc_server_command_dup(cmd));
1773 cmd->pending = TRUE;
1775 silc_buffer_free(res_cmd);
1776 for (k = 0; k < r->res_argc; k++)
1777 silc_free(r->res_argv[k]);
1778 silc_free(r->res_argv);
1779 silc_free(r->res_argv_lens);
1780 silc_free(r->res_argv_types);
1789 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1790 SilcClientEntry *clients,
1791 SilcUInt32 clients_count,
1792 SilcServerEntry *servers,
1793 SilcUInt32 servers_count,
1794 SilcChannelEntry *channels,
1795 SilcUInt32 channels_count,
1798 SilcServer server = cmd->server;
1799 int i, k, len, valid_count;
1800 SilcBuffer packet, idp;
1802 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1803 char nh[256], uh[256];
1804 SilcSocketConnection hsock;
1806 status = SILC_STATUS_OK;
1809 SilcClientEntry entry;
1811 /* Process only valid entries. */
1813 for (i = 0; i < clients_count; i++) {
1814 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1821 /* No valid entries found at all, just send error */
1824 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1826 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1827 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1828 3, tmp, strlen(tmp));
1830 tmp = silc_argument_get_arg_type(cmd->args, 5, (SilcUInt32 *)&len);
1831 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1832 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1838 /* Process all valid client entries and send command replies */
1840 if (valid_count > 1)
1841 status = SILC_STATUS_LIST_START;
1843 for (i = 0, k = 0; i < clients_count; i++) {
1849 status = SILC_STATUS_LIST_ITEM;
1850 if (valid_count > 1 && k == valid_count - 1
1851 && !servers_count && !channels_count)
1852 status = SILC_STATUS_LIST_END;
1853 if (count && k - 1 == count)
1854 status = SILC_STATUS_LIST_END;
1856 /* Send IDENTIFY reply */
1858 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1859 memset(uh, 0, sizeof(uh));
1860 memset(nh, 0, sizeof(nh));
1861 strncat(nh, entry->nickname, strlen(entry->nickname));
1862 if (!strchr(entry->nickname, '@')) {
1863 strncat(nh, "@", 1);
1864 if (entry->servername) {
1865 strncat(nh, entry->servername, strlen(entry->servername));
1867 len = entry->router ? strlen(entry->router->server_name) :
1868 strlen(server->server_name);
1869 strncat(nh, entry->router ? entry->router->server_name :
1870 server->server_name, len);
1874 if (!entry->username) {
1875 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1876 status, 0, ident, 2,
1877 2, idp->data, idp->len,
1880 strncat(uh, entry->username, strlen(entry->username));
1881 if (!strchr(entry->username, '@') && entry->connection) {
1882 strncat(uh, "@", 1);
1883 hsock = (SilcSocketConnection)entry->connection;
1884 len = strlen(hsock->hostname);
1885 strncat(uh, hsock->hostname, len);
1888 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1889 status, 0, ident, 3,
1890 2, idp->data, idp->len,
1895 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1896 0, packet->data, packet->len, FALSE);
1898 silc_buffer_free(packet);
1899 silc_buffer_free(idp);
1901 if (count && k - 1 == count)
1909 SilcServerEntry entry;
1911 if (status == SILC_STATUS_OK && servers_count > 1)
1912 status = SILC_STATUS_LIST_START;
1914 for (i = 0, k = 0; i < servers_count; i++) {
1918 status = SILC_STATUS_LIST_ITEM;
1919 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1920 status = SILC_STATUS_LIST_END;
1921 if (count && k - 1 == count)
1922 status = SILC_STATUS_LIST_END;
1924 /* Send IDENTIFY reply */
1925 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1927 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1928 status, 0, ident, 2,
1929 2, idp->data, idp->len,
1930 3, entry->server_name,
1931 entry->server_name ?
1932 strlen(entry->server_name) : 0);
1933 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1934 0, packet->data, packet->len, FALSE);
1936 silc_buffer_free(packet);
1937 silc_buffer_free(idp);
1939 if (count && k - 1 == count)
1947 SilcChannelEntry entry;
1949 if (status == SILC_STATUS_OK && channels_count > 1)
1950 status = SILC_STATUS_LIST_START;
1952 for (i = 0, k = 0; i < channels_count; i++) {
1953 entry = channels[i];
1956 status = SILC_STATUS_LIST_ITEM;
1957 if (channels_count > 1 && k == channels_count - 1)
1958 status = SILC_STATUS_LIST_END;
1959 if (count && k - 1 == count)
1960 status = SILC_STATUS_LIST_END;
1962 /* Send IDENTIFY reply */
1963 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1965 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1966 status, 0, ident, 2,
1967 2, idp->data, idp->len,
1968 3, entry->channel_name,
1969 entry->channel_name ?
1970 strlen(entry->channel_name): 0);
1971 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1972 0, packet->data, packet->len, FALSE);
1974 silc_buffer_free(packet);
1975 silc_buffer_free(idp);
1977 if (count && k - 1 == count)
1986 silc_server_command_identify_process(SilcServerCommandContext cmd)
1988 SilcUInt32 count = 0;
1990 SilcClientEntry *clients = NULL;
1991 SilcServerEntry *servers = NULL;
1992 SilcChannelEntry *channels = NULL;
1993 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
1995 /* Parse the IDENTIFY request */
1996 ret = silc_server_command_identify_parse(cmd,
1997 &clients, &clients_count,
1998 &servers, &servers_count,
1999 &channels, &channels_count,
2005 /* Check that all mandatory fields are present and request those data
2006 from the server who owns the client if necessary. */
2007 if (clients && !silc_server_command_identify_check_client(cmd, clients,
2013 /* Send the command reply to the client */
2014 silc_server_command_identify_send_reply(cmd,
2015 clients, clients_count,
2016 servers, servers_count,
2017 channels, channels_count,
2023 silc_free(channels);
2027 SILC_SERVER_CMD_FUNC(identify)
2029 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2032 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2034 ret = silc_server_command_identify_process(cmd);
2035 silc_server_command_free(cmd);
2038 /* Server side of command NICK. Sets nickname for user. Setting
2039 nickname causes generation of a new client ID for the client. The
2040 new client ID is sent to the client after changing the nickname. */
2042 SILC_SERVER_CMD_FUNC(nick)
2044 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2045 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2046 SilcServer server = cmd->server;
2047 SilcBuffer packet, nidp, oidp = NULL;
2048 SilcClientID *new_id;
2049 SilcUInt32 nick_len;
2051 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2054 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2057 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2059 /* Check nickname */
2060 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2063 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2064 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2065 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2069 /* Check for same nickname */
2070 if (!strcmp(client->nickname, nick)) {
2071 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2075 /* Create new Client ID */
2076 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2078 cmd->server->md5hash, nick,
2082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2083 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2086 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2089 /* Send notify about nickname change to our router. We send the new
2090 ID and ask to replace it with the old one. If we are router the
2091 packet is broadcasted. Send NICK_CHANGE notify. */
2092 if (!server->standalone)
2093 silc_server_send_notify_nick_change(server, server->router->connection,
2094 server->server_type == SILC_SERVER ?
2095 FALSE : TRUE, client->id,
2098 /* Check if anyone is watching the old nickname */
2099 if (server->server_type == SILC_ROUTER)
2100 silc_server_check_watcher_list(server, client, nick,
2101 SILC_NOTIFY_TYPE_NICK_CHANGE);
2103 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2105 /* Remove old cache entry */
2106 silc_idcache_del_by_context(server->local_list->clients, client);
2108 silc_free(client->id);
2109 client->id = new_id;
2111 silc_free(client->nickname);
2112 client->nickname = strdup(nick);
2114 /* Update client cache */
2115 silc_idcache_add(server->local_list->clients, client->nickname,
2116 client->id, (void *)client, 0, NULL);
2118 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2120 /* Send NICK_CHANGE notify to the client's channels */
2121 silc_server_send_notify_on_channels(server, NULL, client,
2122 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2123 oidp->data, oidp->len,
2124 nidp->data, nidp->len,
2126 strlen(client->nickname));
2128 /* Check if anyone is watching the new nickname */
2129 if (server->server_type == SILC_ROUTER)
2130 silc_server_check_watcher_list(server, client, NULL,
2131 SILC_NOTIFY_TYPE_NICK_CHANGE);
2134 /* Send the new Client ID as reply command back to client */
2135 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2136 SILC_STATUS_OK, 0, ident, 2,
2137 2, nidp->data, nidp->len,
2138 3, nick, strlen(nick));
2139 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2140 0, packet->data, packet->len, FALSE);
2142 silc_buffer_free(packet);
2143 silc_buffer_free(nidp);
2145 silc_buffer_free(oidp);
2148 silc_server_command_free(cmd);
2151 /* Sends the LIST command reply */
2154 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2155 SilcChannelEntry *lch,
2156 SilcUInt32 lch_count,
2157 SilcChannelEntry *gch,
2158 SilcUInt32 gch_count)
2161 SilcBuffer packet, idp;
2162 SilcChannelEntry entry;
2164 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2166 unsigned char usercount[4];
2168 int valid_lcount = 0, valid_rcount = 0;
2170 for (i = 0; i < lch_count; i++) {
2171 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2176 for (i = 0; i < gch_count; i++) {
2177 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2183 status = SILC_STATUS_OK;
2184 if ((lch_count + gch_count) > 1)
2185 status = SILC_STATUS_LIST_START;
2188 for (i = 0, k = 0; i < lch_count; i++) {
2194 status = SILC_STATUS_LIST_ITEM;
2195 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2196 status = SILC_STATUS_LIST_END;
2198 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2200 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2201 topic = "*private*";
2202 memset(usercount, 0, sizeof(usercount));
2204 topic = entry->topic;
2205 users = silc_hash_table_count(entry->user_list);
2206 SILC_PUT32_MSB(users, usercount);
2209 /* Send the reply */
2211 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2212 status, 0, ident, 4,
2213 2, idp->data, idp->len,
2214 3, entry->channel_name,
2215 strlen(entry->channel_name),
2216 4, topic, topic ? strlen(topic) : 0,
2218 silc_server_packet_send(cmd->server, cmd->sock,
2219 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2220 packet->len, FALSE);
2221 silc_buffer_free(packet);
2222 silc_buffer_free(idp);
2227 for (i = 0, k = 0; i < gch_count; i++) {
2233 status = SILC_STATUS_LIST_ITEM;
2234 if (valid_rcount > 1 && k == valid_rcount - 1)
2235 status = SILC_STATUS_LIST_END;
2237 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2239 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2240 topic = "*private*";
2241 memset(usercount, 0, sizeof(usercount));
2243 topic = entry->topic;
2244 users = entry->user_count;
2245 SILC_PUT32_MSB(users, usercount);
2248 /* Send the reply */
2250 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2251 status, 0, ident, 4,
2252 2, idp->data, idp->len,
2253 3, entry->channel_name,
2254 strlen(entry->channel_name),
2255 4, topic, topic ? strlen(topic) : 0,
2257 silc_server_packet_send(cmd->server, cmd->sock,
2258 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2259 packet->len, FALSE);
2260 silc_buffer_free(packet);
2261 silc_buffer_free(idp);
2266 /* Server side of LIST command. This lists the channel of the requested
2267 server. Secret channels are not listed. */
2269 SILC_SERVER_CMD_FUNC(list)
2271 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2272 SilcServer server = cmd->server;
2273 SilcChannelID *channel_id = NULL;
2276 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2277 SilcUInt32 lch_count = 0, gch_count = 0;
2279 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2281 /* If we are normal server, send the command to router, since we
2282 want to know all channels in the network. */
2283 if (!cmd->pending && server->server_type == SILC_SERVER &&
2284 !server->standalone) {
2286 SilcUInt16 old_ident;
2288 old_ident = silc_command_get_ident(cmd->payload);
2289 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2290 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2291 silc_server_packet_send(server, server->router->connection,
2292 SILC_PACKET_COMMAND, cmd->packet->flags,
2293 tmpbuf->data, tmpbuf->len, TRUE);
2295 /* Reprocess this packet after received reply from router */
2296 silc_server_command_pending(server, SILC_COMMAND_LIST,
2297 silc_command_get_ident(cmd->payload),
2298 silc_server_command_list,
2299 silc_server_command_dup(cmd));
2300 cmd->pending = TRUE;
2301 silc_command_set_ident(cmd->payload, old_ident);
2302 silc_buffer_free(tmpbuf);
2306 /* Get Channel ID */
2307 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2309 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2312 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2317 /* Get the channels from local list */
2318 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2321 /* Get the channels from global list */
2322 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2325 /* Send the reply */
2326 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2327 gchannels, gch_count);
2329 silc_free(lchannels);
2330 silc_free(gchannels);
2333 silc_server_command_free(cmd);
2336 /* Server side of TOPIC command. Sets topic for channel and/or returns
2337 current topic to client. */
2339 SILC_SERVER_CMD_FUNC(topic)
2341 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2342 SilcServer server = cmd->server;
2343 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2344 SilcChannelID *channel_id;
2345 SilcChannelEntry channel;
2346 SilcChannelClientEntry chl;
2347 SilcBuffer packet, idp;
2349 SilcUInt32 argc, tmp_len;
2350 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2352 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2354 argc = silc_argument_get_arg_num(cmd->args);
2356 /* Get Channel ID */
2357 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2360 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2363 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2365 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2366 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2370 /* Check whether the channel exists */
2371 channel = silc_idlist_find_channel_by_id(server->local_list,
2374 channel = silc_idlist_find_channel_by_id(server->global_list,
2377 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2378 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2386 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2389 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2394 if (strlen(tmp) > 256) {
2395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2396 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2401 /* See whether the client is on channel and has rights to change topic */
2402 if (!silc_server_client_on_channel(client, channel, &chl)) {
2403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2404 SILC_STATUS_ERR_NOT_ON_CHANNEL,
2409 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2410 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2411 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2413 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2418 /* Set the topic for channel */
2419 silc_free(channel->topic);
2420 channel->topic = strdup(tmp);
2422 /* Send TOPIC_SET notify type to the network */
2423 if (!server->standalone)
2424 silc_server_send_notify_topic_set(server, server->router->connection,
2425 server->server_type == SILC_ROUTER ?
2426 TRUE : FALSE, channel,
2427 client->id, SILC_ID_CLIENT,
2430 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2432 /* Send notify about topic change to all clients on the channel */
2433 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2434 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2435 idp->data, idp->len,
2436 channel->topic, strlen(channel->topic));
2437 silc_buffer_free(idp);
2440 /* Send the topic to client as reply packet */
2441 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2442 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2443 SILC_STATUS_OK, 0, ident, 2,
2444 2, idp->data, idp->len,
2447 strlen(channel->topic) : 0);
2448 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2449 0, packet->data, packet->len, FALSE);
2451 silc_buffer_free(packet);
2452 silc_buffer_free(idp);
2453 silc_free(channel_id);
2456 silc_server_command_free(cmd);
2459 /* Server side of INVITE command. Invites some client to join some channel.
2460 This command is also used to manage the invite list of the channel. */
2462 SILC_SERVER_CMD_FUNC(invite)
2464 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2465 SilcServer server = cmd->server;
2466 SilcSocketConnection sock = cmd->sock, dest_sock;
2467 SilcChannelClientEntry chl;
2468 SilcClientEntry sender, dest;
2469 SilcClientID *dest_id = NULL;
2470 SilcChannelEntry channel;
2471 SilcChannelID *channel_id = NULL;
2472 SilcIDListData idata;
2473 SilcBuffer idp, idp2, packet;
2474 unsigned char *tmp, *add, *del;
2476 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2478 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2480 /* Get Channel ID */
2481 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2484 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2487 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2489 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2490 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2494 /* Get the channel entry */
2495 channel = silc_idlist_find_channel_by_id(server->local_list,
2498 channel = silc_idlist_find_channel_by_id(server->global_list,
2501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2502 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2508 /* Check whether the sender of this command is on the channel. */
2509 sender = (SilcClientEntry)sock->user_data;
2510 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2512 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2516 /* Check whether the channel is invite-only channel. If yes then the
2517 sender of this command must be at least channel operator. */
2518 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2519 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2520 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2521 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2522 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2527 /* Get destination client ID */
2528 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2533 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2535 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2536 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2540 /* Get the client entry */
2541 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2543 if (server->server_type != SILC_SERVER || !resolve) {
2544 silc_server_command_send_status_reply(
2545 cmd, SILC_COMMAND_INVITE,
2546 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2550 /* The client info is being resolved. Reprocess this packet after
2551 receiving the reply to the query. */
2552 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2554 silc_server_command_invite,
2555 silc_server_command_dup(cmd));
2556 cmd->pending = TRUE;
2557 silc_free(channel_id);
2562 /* Check whether the requested client is already on the channel. */
2563 if (silc_server_client_on_channel(dest, channel, NULL)) {
2564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2565 SILC_STATUS_ERR_USER_ON_CHANNEL,
2570 /* Get route to the client */
2571 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2574 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2575 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2580 memset(invite, 0, sizeof(invite));
2581 strncat(invite, dest->nickname, strlen(dest->nickname));
2582 strncat(invite, "!", 1);
2583 strncat(invite, dest->username, strlen(dest->username));
2584 if (!strchr(dest->username, '@')) {
2585 strncat(invite, "@", 1);
2586 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2589 len = strlen(invite);
2590 if (!channel->invite_list)
2591 channel->invite_list = silc_calloc(len + 2,
2592 sizeof(*channel->invite_list));
2594 channel->invite_list = silc_realloc(channel->invite_list,
2595 sizeof(*channel->invite_list) *
2597 strlen(channel->invite_list) + 2));
2598 strncat(channel->invite_list, invite, len);
2599 strncat(channel->invite_list, ",", 1);
2601 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2602 /* Send notify to the client that is invited to the channel */
2603 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2604 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2605 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2607 SILC_NOTIFY_TYPE_INVITE, 3,
2608 idp->data, idp->len,
2609 channel->channel_name,
2610 strlen(channel->channel_name),
2611 idp2->data, idp2->len);
2612 silc_buffer_free(idp);
2613 silc_buffer_free(idp2);
2617 /* Add the client to the invite list of the channel */
2618 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2620 if (!channel->invite_list)
2621 channel->invite_list = silc_calloc(len + 2,
2622 sizeof(*channel->invite_list));
2624 channel->invite_list = silc_realloc(channel->invite_list,
2625 sizeof(*channel->invite_list) *
2627 strlen(channel->invite_list) + 2));
2628 if (add[len - 1] == ',')
2629 add[len - 1] = '\0';
2631 strncat(channel->invite_list, add, len);
2632 strncat(channel->invite_list, ",", 1);
2635 /* Get the invite to be removed and remove it from the list */
2636 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2637 if (del && channel->invite_list) {
2638 char *start, *end, *n;
2640 if (!strncmp(channel->invite_list, del,
2641 strlen(channel->invite_list) - 1)) {
2642 silc_free(channel->invite_list);
2643 channel->invite_list = NULL;
2645 start = strstr(channel->invite_list, del);
2646 if (start && strlen(start) >= len) {
2648 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2649 strncat(n, channel->invite_list, start - channel->invite_list);
2650 strncat(n, end + 1, ((channel->invite_list +
2651 strlen(channel->invite_list)) - end) - 1);
2652 silc_free(channel->invite_list);
2653 channel->invite_list = n;
2658 /* Send notify to the primary router */
2659 if (!server->standalone)
2660 silc_server_send_notify_invite(server, server->router->connection,
2661 server->server_type == SILC_ROUTER ?
2662 TRUE : FALSE, channel,
2663 sender->id, add, del);
2665 /* Send command reply */
2666 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2670 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2671 SILC_STATUS_OK, 0, ident, 2,
2673 3, channel->invite_list,
2674 channel->invite_list ?
2675 strlen(channel->invite_list) : 0);
2678 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2679 SILC_STATUS_OK, 0, ident, 1,
2681 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2682 packet->data, packet->len, FALSE);
2683 silc_buffer_free(packet);
2687 silc_free(channel_id);
2688 silc_server_command_free(cmd);
2693 SilcSocketConnection sock;
2697 /* Quits connection to client. This gets called if client won't
2698 close the connection even when it has issued QUIT command. */
2700 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2702 QuitInternal q = (QuitInternal)context;
2704 /* Free all client specific data, such as client entry and entires
2705 on channels this client may be on. */
2706 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2708 q->sock->user_data = NULL;
2710 /* Close the connection on our side */
2711 silc_server_close_connection(q->server, q->sock);
2713 silc_free(q->signoff);
2717 /* Quits SILC session. This is the normal way to disconnect client. */
2719 SILC_SERVER_CMD_FUNC(quit)
2721 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2722 SilcServer server = cmd->server;
2723 SilcSocketConnection sock = cmd->sock;
2725 unsigned char *tmp = NULL;
2728 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2730 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2734 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2738 q = silc_calloc(1, sizeof(*q));
2741 q->signoff = tmp ? strdup(tmp) : NULL;
2743 /* We quit the connection with little timeout */
2744 silc_schedule_task_add(server->schedule, sock->sock,
2745 silc_server_command_quit_cb, (void *)q,
2746 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2749 silc_server_command_free(cmd);
2752 /* Server side of command KILL. This command is used by router operator
2753 to remove an client from the SILC Network temporarily. */
2755 SILC_SERVER_CMD_FUNC(kill)
2757 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2758 SilcServer server = cmd->server;
2759 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2760 SilcClientEntry remote_client;
2761 SilcClientID *client_id;
2762 unsigned char *tmp, *comment;
2763 SilcUInt32 tmp_len, tmp_len2;
2766 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2768 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2771 /* KILL command works only on router */
2772 if (server->server_type != SILC_ROUTER) {
2773 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2774 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2778 /* Check whether client has the permissions. */
2779 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2780 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2781 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2785 /* Get the client ID */
2786 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2789 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2793 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2796 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2801 /* Get the client entry */
2802 remote_client = silc_idlist_find_client_by_id(server->local_list,
2803 client_id, TRUE, NULL);
2805 if (!remote_client) {
2806 remote_client = silc_idlist_find_client_by_id(server->global_list,
2807 client_id, TRUE, NULL);
2809 if (!remote_client) {
2810 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2811 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2818 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2822 /* Send reply to the sender */
2823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2826 /* Check if anyone is watching this nickname */
2827 if (server->server_type == SILC_ROUTER)
2828 silc_server_check_watcher_list(server, client, NULL,
2829 SILC_NOTIFY_TYPE_KILLED);
2831 /* Now do the killing */
2832 silc_server_kill_client(server, remote_client, comment, client->id,
2836 silc_server_command_free(cmd);
2839 /* Server side of command INFO. This sends information about us to
2840 the client. If client requested specific server we will send the
2841 command to that server. */
2843 SILC_SERVER_CMD_FUNC(info)
2845 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2846 SilcServer server = cmd->server;
2847 SilcBuffer packet, idp;
2850 char *dest_server, *server_info = NULL, *server_name;
2851 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2852 SilcServerEntry entry = NULL;
2853 SilcServerID *server_id = NULL;
2855 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2857 /* Get server name */
2858 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2861 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2863 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2865 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2866 SILC_STATUS_ERR_NO_SERVER_ID, 0);
2872 /* Check whether we have this server cached */
2873 entry = silc_idlist_find_server_by_id(server->local_list,
2874 server_id, TRUE, NULL);
2876 entry = silc_idlist_find_server_by_id(server->global_list,
2877 server_id, TRUE, NULL);
2878 if (!entry && server->server_type != SILC_SERVER) {
2879 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2880 SILC_STATUS_ERR_NO_SUCH_SERVER,
2887 /* Some buggy servers has sent request to router about themselves. */
2888 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2891 if ((!dest_server && !server_id && !entry) || (entry &&
2892 entry == server->id_entry) ||
2893 (dest_server && !cmd->pending &&
2894 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2895 /* Send our reply */
2896 char info_string[256];
2898 memset(info_string, 0, sizeof(info_string));
2899 snprintf(info_string, sizeof(info_string),
2900 "location: %s server: %s admin: %s <%s>",
2901 server->config->server_info->location,
2902 server->config->server_info->server_type,
2903 server->config->server_info->admin,
2904 server->config->server_info->email);
2906 server_info = info_string;
2907 entry = server->id_entry;
2909 /* Check whether we have this server cached */
2910 if (!entry && dest_server) {
2911 entry = silc_idlist_find_server_by_name(server->global_list,
2912 dest_server, TRUE, NULL);
2914 entry = silc_idlist_find_server_by_name(server->local_list,
2915 dest_server, TRUE, NULL);
2919 if (!cmd->pending &&
2920 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2921 /* Send to the server */
2923 SilcUInt16 old_ident;
2925 old_ident = silc_command_get_ident(cmd->payload);
2926 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2927 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2929 silc_server_packet_send(server, entry->connection,
2930 SILC_PACKET_COMMAND, cmd->packet->flags,
2931 tmpbuf->data, tmpbuf->len, TRUE);
2933 /* Reprocess this packet after received reply from router */
2934 silc_server_command_pending(server, SILC_COMMAND_INFO,
2935 silc_command_get_ident(cmd->payload),
2936 silc_server_command_info,
2937 silc_server_command_dup(cmd));
2938 cmd->pending = TRUE;
2939 silc_command_set_ident(cmd->payload, old_ident);
2940 silc_buffer_free(tmpbuf);
2944 if (!entry && !cmd->pending && !server->standalone) {
2945 /* Send to the primary router */
2947 SilcUInt16 old_ident;
2949 old_ident = silc_command_get_ident(cmd->payload);
2950 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2951 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2953 silc_server_packet_send(server, server->router->connection,
2954 SILC_PACKET_COMMAND, cmd->packet->flags,
2955 tmpbuf->data, tmpbuf->len, TRUE);
2957 /* Reprocess this packet after received reply from router */
2958 silc_server_command_pending(server, SILC_COMMAND_INFO,
2959 silc_command_get_ident(cmd->payload),
2960 silc_server_command_info,
2961 silc_server_command_dup(cmd));
2962 cmd->pending = TRUE;
2963 silc_command_set_ident(cmd->payload, old_ident);
2964 silc_buffer_free(tmpbuf);
2969 silc_free(server_id);
2972 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2973 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2977 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2979 server_info = entry->server_info;
2980 server_name = entry->server_name;
2982 /* Send the reply */
2983 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2984 SILC_STATUS_OK, 0, ident, 3,
2985 2, idp->data, idp->len,
2987 strlen(server_name),
2990 strlen(server_info) : 0);
2991 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2992 packet->data, packet->len, FALSE);
2994 silc_buffer_free(packet);
2995 silc_buffer_free(idp);
2998 silc_server_command_free(cmd);
3001 /* Server side of command PING. This just replies to the ping. */
3003 SILC_SERVER_CMD_FUNC(ping)
3005 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3006 SilcServer server = cmd->server;
3011 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3014 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3016 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3017 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3020 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3024 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3025 /* Send our reply */
3026 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3030 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3037 silc_server_command_free(cmd);
3040 /* Server side of command STATS. */
3042 SILC_SERVER_CMD_FUNC(stats)
3044 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3045 SilcServer server = cmd->server;
3046 SilcServerID *server_id;
3049 SilcBuffer packet, stats;
3050 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3053 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3056 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3058 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3059 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3062 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3066 /* The ID must be ours */
3067 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3068 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3069 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3070 silc_free(server_id);
3073 silc_free(server_id);
3075 /* If we are router then just send everything we got. If we are normal
3076 server then we'll send this to our router to get all the latest
3077 statistical information. */
3078 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3079 !server->standalone) {
3080 /* Send request to our router */
3081 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3083 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3084 ++server->cmd_ident, 1,
3085 1, idp->data, idp->len);
3086 silc_server_packet_send(server, server->router->connection,
3087 SILC_PACKET_COMMAND, 0, packet->data,
3088 packet->len, FALSE);
3090 /* Reprocess this packet after received reply from router */
3091 silc_server_command_pending(server, SILC_COMMAND_STATS,
3093 silc_server_command_stats,
3094 silc_server_command_dup(cmd));
3095 cmd->pending = TRUE;
3096 silc_buffer_free(packet);
3097 silc_buffer_free(idp);
3101 /* Send our reply to sender */
3102 uptime = time(NULL) - server->starttime;
3104 stats = silc_buffer_alloc_size(60);
3105 silc_buffer_format(stats,
3106 SILC_STR_UI_INT(server->starttime),
3107 SILC_STR_UI_INT(uptime),
3108 SILC_STR_UI_INT(server->stat.my_clients),
3109 SILC_STR_UI_INT(server->stat.my_channels),
3110 SILC_STR_UI_INT(server->stat.my_server_ops),
3111 SILC_STR_UI_INT(server->stat.my_router_ops),
3112 SILC_STR_UI_INT(server->stat.cell_clients),
3113 SILC_STR_UI_INT(server->stat.cell_channels),
3114 SILC_STR_UI_INT(server->stat.cell_servers),
3115 SILC_STR_UI_INT(server->stat.clients),
3116 SILC_STR_UI_INT(server->stat.channels),
3117 SILC_STR_UI_INT(server->stat.servers),
3118 SILC_STR_UI_INT(server->stat.routers),
3119 SILC_STR_UI_INT(server->stat.server_ops),
3120 SILC_STR_UI_INT(server->stat.router_ops),
3123 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3124 SILC_STATUS_OK, 0, ident, 2,
3126 3, stats->data, stats->len);
3127 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3128 0, packet->data, packet->len, FALSE);
3129 silc_buffer_free(packet);
3130 silc_buffer_free(stats);
3133 silc_server_command_free(cmd);
3136 /* Internal routine to join channel. The channel sent to this function
3137 has been either created or resolved from ID lists. This joins the sent
3138 client to the channel. */
3140 static void silc_server_command_join_channel(SilcServer server,
3141 SilcServerCommandContext cmd,
3142 SilcChannelEntry channel,
3143 SilcClientID *client_id,
3147 const unsigned char *auth,
3148 SilcUInt32 auth_len)
3150 SilcSocketConnection sock = cmd->sock;
3152 SilcUInt32 tmp_len, user_count;
3153 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3154 SilcClientEntry client;
3155 SilcChannelClientEntry chl;
3156 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3157 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3158 char check[512], check2[512];
3159 bool founder = FALSE;
3162 SILC_LOG_DEBUG(("Start"));
3167 /* Get the client entry */
3168 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3169 client = (SilcClientEntry)sock->user_data;
3171 client = silc_server_get_client_resolve(server, client_id, FALSE,
3178 silc_server_command_send_status_reply(
3179 cmd, SILC_COMMAND_JOIN,
3180 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3184 /* The client info is being resolved. Reprocess this packet after
3185 receiving the reply to the query. */
3186 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3188 silc_server_command_join,
3189 silc_server_command_dup(cmd));
3190 cmd->pending = TRUE;
3194 cmd->pending = FALSE;
3198 * Check founder auth payload if provided. If client can gain founder
3199 * privileges it can override various conditions on joining the channel,
3200 * and can have directly the founder mode set on the channel.
3202 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3203 SilcIDListData idata = (SilcIDListData)client;
3205 if (channel->founder_key && idata->public_key &&
3206 silc_pkcs_public_key_compare(channel->founder_key,
3207 idata->public_key)) {
3208 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3209 (void *)channel->founder_passwd :
3210 (void *)channel->founder_key);
3211 SilcUInt32 auth_data_len =
3212 (channel->founder_method == SILC_AUTH_PASSWORD ?
3213 channel->founder_passwd_len : 0);
3215 /* Check whether the client is to become founder */
3216 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3217 auth_data, auth_data_len,
3218 idata->hash, client->id, SILC_ID_CLIENT)) {
3219 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3226 * Check channel modes
3230 memset(check, 0, sizeof(check));
3231 memset(check2, 0, sizeof(check2));
3232 strncat(check, client->nickname, strlen(client->nickname));
3233 strncat(check, "!", 1);
3234 strncat(check, client->username, strlen(client->username));
3235 if (!strchr(client->username, '@')) {
3236 strncat(check, "@", 1);
3237 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3240 strncat(check2, client->nickname, strlen(client->nickname));
3241 if (!strchr(client->nickname, '@')) {
3242 strncat(check2, "@", 1);
3243 strncat(check2, server->server_name, strlen(server->server_name));
3245 strncat(check2, "!", 1);
3246 strncat(check2, client->username, strlen(client->username));
3247 if (!strchr(client->username, '@')) {
3248 strncat(check2, "@", 1);
3249 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3252 /* Check invite list if channel is invite-only channel */
3253 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3254 if (!channel->invite_list ||
3255 (!silc_string_match(channel->invite_list, check) &&
3256 !silc_string_match(channel->invite_list, check2))) {
3257 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3258 SILC_STATUS_ERR_NOT_INVITED, 0);
3263 /* Check ban list if it exists. If the client's nickname, server,
3264 username and/or hostname is in the ban list the access to the
3265 channel is denied. */
3266 if (channel->ban_list) {
3267 if (silc_string_match(channel->ban_list, check) ||
3268 silc_string_match(channel->ban_list, check2)) {
3269 silc_server_command_send_status_reply(
3270 cmd, SILC_COMMAND_JOIN,
3271 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3276 /* Check user count limit if set. */
3277 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3278 if (silc_hash_table_count(channel->user_list) + 1 >
3279 channel->user_limit) {
3280 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3281 SILC_STATUS_ERR_CHANNEL_IS_FULL,
3288 /* Check the channel passphrase if set. */
3289 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3290 /* Get passphrase */
3291 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3293 passphrase = silc_memdup(tmp, tmp_len);
3295 if (!passphrase || !channel->passphrase ||
3296 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3298 SILC_STATUS_ERR_BAD_PASSWORD, 0);
3304 * Client is allowed to join to the channel. Make it happen.
3307 /* Check whether the client already is on the channel */
3308 if (silc_server_client_on_channel(client, channel, NULL)) {
3309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3310 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3314 /* Generate new channel key as protocol dictates */
3316 if (!silc_server_create_channel_key(server, channel, 0))
3319 /* Send the channel key. This is broadcasted to the channel but is not
3320 sent to the client who is joining to the channel. */
3321 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3322 silc_server_send_channel_key(server, NULL, channel,
3323 server->server_type == SILC_ROUTER ?
3324 FALSE : !server->standalone);
3327 /* Join the client to the channel by adding it to channel's user list.
3328 Add also the channel to client entry's channels list for fast cross-
3330 chl = silc_calloc(1, sizeof(*chl));
3332 chl->client = client;
3333 chl->channel = channel;
3334 silc_hash_table_add(channel->user_list, client, chl);
3335 silc_hash_table_add(client->channels, channel, chl);
3336 channel->user_count++;
3338 /* Get users on the channel */
3339 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3342 /* Encode Client ID Payload of the original client who wants to join */
3343 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3345 /* Encode command reply packet */
3346 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3347 SILC_PUT32_MSB(channel->mode, mode);
3348 SILC_PUT32_MSB(created, tmp2);
3349 SILC_PUT32_MSB(user_count, tmp3);
3351 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3352 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3353 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3356 strlen(channel->channel_key->
3358 channel->channel_key->cipher->name,
3359 channel->key_len / 8, channel->key);
3364 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3365 SILC_STATUS_OK, 0, ident, 13,
3366 2, channel->channel_name,
3367 strlen(channel->channel_name),
3368 3, chidp->data, chidp->len,
3369 4, clidp->data, clidp->len,
3372 7, keyp ? keyp->data : NULL,
3373 keyp ? keyp->len : 0,
3374 8, channel->ban_list,
3376 strlen(channel->ban_list) : 0,
3377 9, channel->invite_list,
3378 channel->invite_list ?
3379 strlen(channel->invite_list) : 0,
3382 strlen(channel->topic) : 0,
3383 11, silc_hmac_get_name(channel->hmac),
3384 strlen(silc_hmac_get_name(channel->
3387 13, user_list->data, user_list->len,
3388 14, mode_list->data,
3391 /* Send command reply */
3392 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3393 reply->data, reply->len, FALSE);
3395 /* Send JOIN notify to locally connected clients on the channel. If
3396 we are normal server then router will send or have sent JOIN notify
3397 already. However since we've added the client already to our channel
3398 we'll ignore it (in packet_receive.c) so we must send it here. If
3399 we are router then this will send it to local clients and local
3401 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3402 SILC_NOTIFY_TYPE_JOIN, 2,
3403 clidp->data, clidp->len,
3404 chidp->data, chidp->len);
3406 if (!cmd->pending) {
3407 /* Send JOIN notify packet to our primary router */
3408 if (!server->standalone)
3409 silc_server_send_notify_join(server, server->router->connection,
3410 server->server_type == SILC_ROUTER ?
3411 TRUE : FALSE, channel, client->id);
3414 /* Distribute the channel key to all backup routers. */
3415 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3416 keyp->data, keyp->len, FALSE, TRUE);
3419 /* If client became founder by providing correct founder auth data
3420 notify the mode change to the channel. */
3422 SILC_PUT32_MSB(chl->mode, mode);
3423 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3424 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3425 clidp->data, clidp->len,
3426 mode, 4, clidp->data, clidp->len);
3428 /* Set CUMODE notify type to network */
3429 if (!server->standalone)
3430 silc_server_send_notify_cumode(server, server->router->connection,
3431 server->server_type == SILC_ROUTER ?
3432 TRUE : FALSE, channel,
3433 chl->mode, client->id, SILC_ID_CLIENT,
3437 silc_buffer_free(reply);
3438 silc_buffer_free(clidp);
3439 silc_buffer_free(chidp);
3440 silc_buffer_free(keyp);
3441 silc_buffer_free(user_list);
3442 silc_buffer_free(mode_list);
3445 silc_free(passphrase);
3448 /* Server side of command JOIN. Joins client into requested channel. If
3449 the channel does not exist it will be created. */
3451 SILC_SERVER_CMD_FUNC(join)
3453 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3454 SilcServer server = cmd->server;
3455 unsigned char *auth;
3456 SilcUInt32 tmp_len, auth_len;
3457 char *tmp, *channel_name = NULL, *cipher, *hmac;
3458 SilcChannelEntry channel;
3459 SilcUInt32 umode = 0;
3460 bool created = FALSE, create_key = TRUE;
3461 SilcClientID *client_id;
3463 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3465 /* Get channel name */
3466 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3468 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3469 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3476 channel_name[255] = '\0';
3478 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3480 SILC_STATUS_ERR_BAD_CHANNEL, 0);
3484 /* Get Client ID of the client who is joining to the channel */
3485 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3488 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3492 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3494 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3495 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3500 /* Get cipher, hmac name and auth payload */
3501 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3502 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3503 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3505 /* See if the channel exists */
3506 channel = silc_idlist_find_channel_by_name(server->local_list,
3507 channel_name, NULL);
3509 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3510 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3511 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3513 if (!channel || channel->disabled) {
3514 /* Channel not found */
3516 /* If we are standalone server we don't have a router, we just create
3517 the channel by ourselves. */
3518 if (server->standalone) {
3519 channel = silc_server_create_new_channel(server, server->id, cipher,
3520 hmac, channel_name, TRUE);
3522 silc_server_command_send_status_reply(
3523 cmd, SILC_COMMAND_JOIN,
3524 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3529 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3535 /* The channel does not exist on our server. If we are normal server
3536 we will send JOIN command to our router which will handle the
3537 joining procedure (either creates the channel if it doesn't exist
3538 or joins the client to it). */
3539 if (server->server_type != SILC_ROUTER) {
3541 SilcUInt16 old_ident;
3543 /* If this is pending command callback then we've resolved
3544 it and it didn't work, return since we've notified the
3545 client already in the command reply callback. */
3549 old_ident = silc_command_get_ident(cmd->payload);
3550 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3551 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3553 /* Send JOIN command to our router */
3554 silc_server_packet_send(server, (SilcSocketConnection)
3555 server->router->connection,
3556 SILC_PACKET_COMMAND, cmd->packet->flags,
3557 tmpbuf->data, tmpbuf->len, TRUE);
3559 /* Reprocess this packet after received reply from router */
3560 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3561 silc_command_get_ident(cmd->payload),
3562 silc_server_command_join,
3563 silc_server_command_dup(cmd));
3564 cmd->pending = TRUE;
3565 silc_command_set_ident(cmd->payload, old_ident);
3566 silc_buffer_free(tmpbuf);
3570 /* We are router and the channel does not seem exist so we will check
3571 our global list as well for the channel. */
3572 channel = silc_idlist_find_channel_by_name(server->global_list,
3573 channel_name, NULL);
3575 /* Channel really does not exist, create it */
3576 channel = silc_server_create_new_channel(server, server->id, cipher,
3577 hmac, channel_name, TRUE);
3579 silc_server_command_send_status_reply(
3580 cmd, SILC_COMMAND_JOIN,
3581 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3585 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3593 /* Channel not found */
3595 /* If the command came from router and we are normal server then
3596 something went wrong with the joining as the channel was not found.
3597 We can't do anything else but ignore this. */
3598 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3599 server->server_type != SILC_ROUTER)
3602 /* We are router and the channel does not seem exist so we will check
3603 our global list as well for the channel. */
3604 channel = silc_idlist_find_channel_by_name(server->global_list,
3605 channel_name, NULL);
3607 /* Channel really does not exist, create it */
3608 channel = silc_server_create_new_channel(server, server->id, cipher,
3609 hmac, channel_name, TRUE);
3611 silc_server_command_send_status_reply(
3612 cmd, SILC_COMMAND_JOIN,
3613 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3617 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3624 /* Check whether the channel was created by our router */
3625 if (cmd->pending && context2) {
3626 SilcServerCommandReplyContext reply = context2;
3628 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3629 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3630 SILC_GET32_MSB(created, tmp);
3631 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3632 create_key = FALSE; /* Router returned the key already */
3635 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3636 !silc_hash_table_count(channel->user_list))
3640 /* If the channel does not have global users and is also empty the client
3641 will be the channel founder and operator. */
3642 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3643 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3645 /* Join to the channel */
3646 silc_server_command_join_channel(server, cmd, channel, client_id,
3647 created, create_key, umode,
3650 silc_free(client_id);
3653 silc_server_command_free(cmd);
3656 /* Server side of command MOTD. Sends server's current "message of the
3657 day" to the client. */
3659 SILC_SERVER_CMD_FUNC(motd)
3661 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3662 SilcServer server = cmd->server;
3663 SilcBuffer packet, idp;
3664 char *motd, *dest_server;
3665 SilcUInt32 motd_len;
3666 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3668 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3670 /* Get server name */
3671 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3674 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3678 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3681 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3683 if (server->config && server->config->server_info &&
3684 server->config->server_info->motd_file) {
3686 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3691 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3698 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3704 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3705 packet->data, packet->len, FALSE);
3706 silc_buffer_free(packet);
3707 silc_buffer_free(idp);
3709 SilcServerEntry entry;
3711 /* Check whether we have this server cached */
3712 entry = silc_idlist_find_server_by_name(server->global_list,
3713 dest_server, TRUE, NULL);
3715 entry = silc_idlist_find_server_by_name(server->local_list,
3716 dest_server, TRUE, NULL);
3719 if (server->server_type != SILC_SERVER && !cmd->pending &&
3720 entry && !entry->motd) {
3721 /* Send to the server */
3723 SilcUInt16 old_ident;
3725 old_ident = silc_command_get_ident(cmd->payload);
3726 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3727 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3729 silc_server_packet_send(server, entry->connection,
3730 SILC_PACKET_COMMAND, cmd->packet->flags,
3731 tmpbuf->data, tmpbuf->len, TRUE);
3733 /* Reprocess this packet after received reply from router */
3734 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3735 silc_command_get_ident(cmd->payload),
3736 silc_server_command_motd,
3737 silc_server_command_dup(cmd));
3738 cmd->pending = TRUE;
3739 silc_command_set_ident(cmd->payload, old_ident);
3740 silc_buffer_free(tmpbuf);
3744 if (!entry && !cmd->pending && !server->standalone) {
3745 /* Send to the primary router */
3747 SilcUInt16 old_ident;
3749 old_ident = silc_command_get_ident(cmd->payload);
3750 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3751 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3753 silc_server_packet_send(server, server->router->connection,
3754 SILC_PACKET_COMMAND, cmd->packet->flags,
3755 tmpbuf->data, tmpbuf->len, TRUE);
3757 /* Reprocess this packet after received reply from router */
3758 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3759 silc_command_get_ident(cmd->payload),
3760 silc_server_command_motd,
3761 silc_server_command_dup(cmd));
3762 cmd->pending = TRUE;
3763 silc_command_set_ident(cmd->payload, old_ident);
3764 silc_buffer_free(tmpbuf);
3769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3770 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3774 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3775 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3776 SILC_STATUS_OK, 0, ident, 2,
3780 strlen(entry->motd) : 0);
3781 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3782 packet->data, packet->len, FALSE);
3783 silc_buffer_free(packet);
3784 silc_buffer_free(idp);
3788 silc_server_command_free(cmd);
3791 /* Server side of command UMODE. Client can use this command to set/unset
3792 user mode. Client actually cannot set itself to be as server/router
3793 operator so this can be used only to unset the modes. */
3795 SILC_SERVER_CMD_FUNC(umode)
3797 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3798 SilcServer server = cmd->server;
3799 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3801 unsigned char *tmp_mask, m[4];
3802 SilcUInt32 mask = 0;
3803 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3804 bool set_mask = FALSE;
3806 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3809 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3811 /* Get the client's mode mask */
3812 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3814 SILC_GET32_MSB(mask, tmp_mask);
3819 /* Check that mode changing is allowed. */
3820 if (!silc_server_check_umode_rights(server, client, mask)) {
3821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3822 SILC_STATUS_ERR_PERM_DENIED, 0);
3826 /* Anonymous mode cannot be set by client */
3827 if (mask & SILC_UMODE_ANONYMOUS) {
3828 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3829 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3830 SILC_STATUS_ERR_PERM_DENIED, 0);
3834 if (client->mode & SILC_UMODE_ANONYMOUS) {
3835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3836 SILC_STATUS_ERR_PERM_DENIED, 0);
3841 /* Change the mode */
3842 client->mode = mask;
3844 /* Send UMODE change to primary router */
3845 if (!server->standalone)
3846 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3847 client->id, client->mode);
3849 /* Check if anyone is watching this nickname */
3850 if (server->server_type == SILC_ROUTER)
3851 silc_server_check_watcher_list(server, client, NULL,
3852 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3855 /* Send command reply to sender */
3856 SILC_PUT32_MSB(client->mode, m);
3857 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3858 SILC_STATUS_OK, 0, ident, 1,
3860 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3861 packet->data, packet->len, FALSE);
3862 silc_buffer_free(packet);
3865 silc_server_command_free(cmd);
3868 /* Server side command of CMODE. Changes channel mode */
3870 SILC_SERVER_CMD_FUNC(cmode)
3872 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3873 SilcServer server = cmd->server;
3874 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3875 SilcIDListData idata = (SilcIDListData)client;
3876 SilcChannelID *channel_id = NULL;
3877 SilcChannelEntry channel;
3878 SilcChannelClientEntry chl;
3879 SilcBuffer packet, cidp;
3880 unsigned char *tmp, *tmp_id, *tmp_mask;
3881 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3882 SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3883 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3884 bool set_mask = FALSE;
3886 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3888 /* Get Channel ID */
3889 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3891 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3892 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3895 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3898 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3902 /* Get the channel mode mask */
3903 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3905 SILC_GET32_MSB(mode_mask, tmp_mask);
3909 /* Get channel entry */
3910 channel = silc_idlist_find_channel_by_id(server->local_list,
3913 channel = silc_idlist_find_channel_by_id(server->global_list,
3916 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3917 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3923 /* Check whether this client is on the channel */
3924 if (!silc_server_client_on_channel(client, channel, &chl)) {
3925 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3926 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3930 /* Check that client has rights to change any requested channel modes */
3931 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
3933 silc_server_command_send_status_reply(
3934 cmd, SILC_COMMAND_CMODE,
3935 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
3936 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3937 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
3941 /* If mode mask was not sent as argument then merely return the current
3942 mode mask to the sender. */
3945 SILC_PUT32_MSB(channel->mode, m);
3946 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3947 SILC_STATUS_OK, 0, ident, 2,
3948 2, tmp_id, tmp_len2,
3950 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3951 packet->data, packet->len, FALSE);
3952 silc_buffer_free(packet);
3957 * Check the modes. Modes that requires nothing special operation are
3961 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3962 /* Channel uses private keys to protect traffic. Client(s) has set the
3963 key locally they want to use, server does not know that key. */
3964 /* Nothing interesting to do here */
3966 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3967 /* The mode is removed and we need to generate and distribute
3968 new channel key. Clients are not using private channel keys
3969 anymore after this. */
3971 /* Re-generate channel key */
3972 if (!silc_server_create_channel_key(server, channel, 0))
3975 /* Send the channel key. This sends it to our local clients and if
3976 we are normal server to our router as well. */
3977 silc_server_send_channel_key(server, NULL, channel,
3978 server->server_type == SILC_ROUTER ?
3979 FALSE : !server->standalone);
3981 cipher = channel->channel_key->cipher->name;
3982 hmac = (char *)silc_hmac_get_name(channel->hmac);
3986 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3987 /* User limit is set on channel */
3988 SilcUInt32 user_limit;
3990 /* Get user limit */
3991 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3993 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3994 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3995 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3999 SILC_GET32_MSB(user_limit, tmp);
4000 channel->user_limit = user_limit;
4003 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4004 /* User limit mode is unset. Remove user limit */
4005 channel->user_limit = 0;
4008 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4009 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4010 /* Passphrase has been set to channel */
4012 /* Get the passphrase */
4013 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4015 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4016 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4020 /* Save the passphrase */
4021 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4024 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4025 /* Passphrase mode is unset. remove the passphrase */
4026 silc_free(channel->passphrase);
4027 channel->passphrase = NULL;
4031 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4032 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4033 /* Cipher to use protect the traffic */
4034 SilcCipher newkey, oldkey;
4037 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4040 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4044 /* Delete old cipher and allocate the new one */
4045 if (!silc_cipher_alloc(cipher, &newkey)) {
4046 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4047 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4051 oldkey = channel->channel_key;
4052 channel->channel_key = newkey;
4054 /* Re-generate channel key */
4055 if (!silc_server_create_channel_key(server, channel, 0)) {
4056 /* We don't have new key, revert to old one */
4057 channel->channel_key = oldkey;
4061 /* Remove old channel key for good */
4062 silc_cipher_free(oldkey);
4064 /* Send the channel key. This sends it to our local clients and if
4065 we are normal server to our router as well. */
4066 silc_server_send_channel_key(server, NULL, channel,
4067 server->server_type == SILC_ROUTER ?
4068 FALSE : !server->standalone);
4071 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4072 /* Cipher mode is unset. Remove the cipher and revert back to
4074 SilcCipher newkey, oldkey;
4075 cipher = channel->cipher;
4077 /* Delete old cipher and allocate default one */
4078 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4079 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4080 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4084 oldkey = channel->channel_key;
4085 channel->channel_key = newkey;
4087 /* Re-generate channel key */
4088 if (!silc_server_create_channel_key(server, channel, 0)) {
4089 /* We don't have new key, revert to old one */
4090 channel->channel_key = oldkey;
4094 /* Remove old channel key for good */
4095 silc_cipher_free(oldkey);
4097 /* Send the channel key. This sends it to our local clients and if
4098 we are normal server to our router as well. */
4099 silc_server_send_channel_key(server, NULL, channel,
4100 server->server_type == SILC_ROUTER ?
4101 FALSE : !server->standalone);
4105 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4106 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4107 /* HMAC to use protect the traffic */
4108 unsigned char hash[32];
4112 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4114 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4115 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4119 /* Delete old hmac and allocate the new one */
4120 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4122 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4126 silc_hmac_free(channel->hmac);
4127 channel->hmac = newhmac;
4129 /* Set the HMAC key out of current channel key. The client must do
4131 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4132 channel->key_len / 8, hash);
4133 silc_hmac_set_key(channel->hmac, hash,
4134 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4135 memset(hash, 0, sizeof(hash));
4138 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4139 /* Hmac mode is unset. Remove the hmac and revert back to
4142 unsigned char hash[32];
4143 hmac = channel->hmac_name;
4145 /* Delete old hmac and allocate default one */
4146 silc_hmac_free(channel->hmac);
4147 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4148 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4149 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4153 silc_hmac_free(channel->hmac);
4154 channel->hmac = newhmac;
4156 /* Set the HMAC key out of current channel key. The client must do
4158 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4159 channel->key_len / 8,
4161 silc_hmac_set_key(channel->hmac, hash,
4162 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4163 memset(hash, 0, sizeof(hash));
4167 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4168 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4169 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4170 /* Set the founder authentication */
4171 SilcAuthPayload auth;
4173 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4175 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4176 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4180 auth = silc_auth_payload_parse(tmp, tmp_len);
4182 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4183 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4187 /* Save the public key */
4188 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4189 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4192 channel->founder_method = silc_auth_get_method(auth);
4194 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4195 tmp = silc_auth_get_data(auth, &tmp_len);
4196 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4197 channel->founder_passwd_len = tmp_len;
4199 /* Verify the payload before setting the mode */
4200 if (!silc_auth_verify(auth, channel->founder_method,
4201 channel->founder_key, 0, idata->hash,
4202 client->id, SILC_ID_CLIENT)) {
4203 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4204 SILC_STATUS_ERR_AUTH_FAILED,
4210 silc_auth_payload_free(auth);
4214 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4215 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4216 if (channel->founder_key)
4217 silc_pkcs_public_key_free(channel->founder_key);
4218 if (channel->founder_passwd) {
4219 silc_free(channel->founder_passwd);
4220 channel->founder_passwd = NULL;
4226 /* Finally, set the mode */
4227 channel->mode = mode_mask;
4229 /* Send CMODE_CHANGE notify. */
4230 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4231 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4232 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4233 cidp->data, cidp->len,
4235 cipher, cipher ? strlen(cipher) : 0,
4236 hmac, hmac ? strlen(hmac) : 0,
4237 passphrase, passphrase ?
4238 strlen(passphrase) : 0);
4240 /* Set CMODE notify type to network */
4241 if (!server->standalone)
4242 silc_server_send_notify_cmode(server, server->router->connection,
4243 server->server_type == SILC_ROUTER ?
4244 TRUE : FALSE, channel,
4245 mode_mask, client->id, SILC_ID_CLIENT,
4246 cipher, hmac, passphrase);
4248 /* Send command reply to sender */
4249 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4250 SILC_STATUS_OK, 0, ident, 2,
4251 2, tmp_id, tmp_len2,
4253 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4254 packet->data, packet->len, FALSE);
4256 silc_buffer_free(packet);
4257 silc_buffer_free(cidp);
4260 silc_free(channel_id);
4261 silc_server_command_free(cmd);
4264 /* Server side of CUMODE command. Changes client's mode on a channel. */
4266 SILC_SERVER_CMD_FUNC(cumode)
4268 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4269 SilcServer server = cmd->server;
4270 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4271 SilcIDListData idata = (SilcIDListData)client;
4272 SilcChannelID *channel_id;
4273 SilcClientID *client_id;
4274 SilcChannelEntry channel;
4275 SilcClientEntry target_client;
4276 SilcChannelClientEntry chl;
4277 SilcBuffer packet, idp;
4278 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4279 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4281 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4283 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4285 /* Get Channel ID */
4286 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4288 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4289 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4292 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4295 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4299 /* Get channel entry */
4300 channel = silc_idlist_find_channel_by_id(server->local_list,
4303 channel = silc_idlist_find_channel_by_id(server->global_list,
4306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4307 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4313 /* Check whether sender is on the channel */
4314 if (!silc_server_client_on_channel(client, channel, &chl)) {
4315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4316 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4319 sender_mask = chl->mode;
4321 /* Get the target client's channel mode mask */
4322 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4325 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4329 SILC_GET32_MSB(target_mask, tmp_mask);
4331 /* Get target Client ID */
4332 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4335 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4338 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4341 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4345 /* Get target client's entry */
4346 target_client = silc_idlist_find_client_by_id(server->local_list,
4347 client_id, TRUE, NULL);
4348 if (!target_client) {
4349 target_client = silc_idlist_find_client_by_id(server->global_list,
4350 client_id, TRUE, NULL);
4353 if (target_client != client &&
4354 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4355 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4357 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4361 /* Check whether target client is on the channel */
4362 if (target_client != client) {
4363 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4364 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4365 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4374 /* If the target client is founder, no one else can change their mode
4376 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4377 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4378 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4383 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4384 if (target_client != client) {
4385 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4386 SILC_STATUS_ERR_NOT_YOU, 0);
4390 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4391 /* The client tries to claim the founder rights. */
4392 unsigned char *tmp_auth;
4393 SilcUInt32 tmp_auth_len, auth_len;
4396 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4397 !channel->founder_key || !idata->public_key ||
4398 !silc_pkcs_public_key_compare(channel->founder_key,
4399 idata->public_key)) {
4400 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4401 SILC_STATUS_ERR_NOT_YOU, 0);
4405 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4408 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4412 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4413 (void *)channel->founder_passwd : (void *)channel->founder_key);
4414 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4415 channel->founder_passwd_len : 0);
4417 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4418 channel->founder_method, auth, auth_len,
4419 idata->hash, client->id, SILC_ID_CLIENT)) {
4420 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4421 SILC_STATUS_ERR_AUTH_FAILED, 0);
4425 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4429 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4430 if (target_client == client) {
4431 /* Remove channel founder rights from itself */
4432 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4436 SILC_STATUS_ERR_NOT_YOU, 0);
4442 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4443 /* Promote to operator */
4444 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4445 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4446 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4448 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4453 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4457 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4458 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4459 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4461 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4466 /* Demote to normal user */
4467 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4472 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4473 if (target_client != client) {
4474 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4475 SILC_STATUS_ERR_NOT_YOU, 0);
4479 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4480 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4484 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4485 if (target_client != client) {
4486 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4487 SILC_STATUS_ERR_NOT_YOU, 0);
4491 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4496 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4497 if (target_client != client) {
4498 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4499 SILC_STATUS_ERR_NOT_YOU, 0);
4503 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4504 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4508 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4509 if (target_client != client) {
4510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4511 SILC_STATUS_ERR_NOT_YOU, 0);
4515 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4520 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4521 if (target_client != client) {
4522 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4523 SILC_STATUS_ERR_NOT_YOU, 0);
4527 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4528 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4532 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4533 if (target_client != client) {
4534 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4535 SILC_STATUS_ERR_NOT_YOU, 0);
4539 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4544 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4545 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4547 /* Send notify to channel, notify only if mode was actually changed. */
4549 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4550 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4551 idp->data, idp->len,
4555 /* Set CUMODE notify type to network */
4556 if (!server->standalone)
4557 silc_server_send_notify_cumode(server, server->router->connection,
4558 server->server_type == SILC_ROUTER ?
4559 TRUE : FALSE, channel,
4560 target_mask, client->id,
4565 /* Send command reply to sender */
4566 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4567 SILC_STATUS_OK, 0, ident, 3,
4569 3, tmp_ch_id, tmp_ch_len,
4570 4, tmp_id, tmp_len);
4571 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4572 packet->data, packet->len, FALSE);
4574 silc_buffer_free(packet);
4575 silc_free(channel_id);
4576 silc_free(client_id);
4577 silc_buffer_free(idp);
4580 silc_server_command_free(cmd);
4583 /* Server side of KICK command. Kicks client out of channel. */
4585 SILC_SERVER_CMD_FUNC(kick)
4587 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4588 SilcServer server = cmd->server;
4589 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4590 SilcClientEntry target_client;
4591 SilcChannelID *channel_id;
4592 SilcClientID *client_id;
4593 SilcChannelEntry channel;
4594 SilcChannelClientEntry chl;
4596 SilcUInt32 tmp_len, target_idp_len;
4597 unsigned char *tmp, *comment, *target_idp;
4599 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4601 /* Get Channel ID */
4602 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4604 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4605 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4608 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4610 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4611 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4615 /* Get channel entry */
4616 channel = silc_idlist_find_channel_by_id(server->local_list,
4619 channel = silc_idlist_find_channel_by_id(server->local_list,
4622 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4623 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4629 /* Check whether sender is on the channel */
4630 if (!silc_server_client_on_channel(client, channel, &chl)) {
4631 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4632 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4636 /* Check that the kicker is channel operator or channel founder */
4637 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4638 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4640 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4644 /* Get target Client ID */
4645 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4647 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4648 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4651 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4653 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4654 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4658 /* Get target client's entry */
4659 target_client = silc_idlist_find_client_by_id(server->local_list,
4660 client_id, TRUE, NULL);
4661 if (!target_client) {
4662 target_client = silc_idlist_find_client_by_id(server->global_list,
4663 client_id, TRUE, NULL);
4666 /* Check whether target client is on the channel */
4667 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4669 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4674 /* Check that the target client is not channel founder. Channel founder
4675 cannot be kicked from the channel. */
4676 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4677 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4678 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4685 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4689 /* Send command reply to sender */
4690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4693 /* Send KICKED notify to local clients on the channel */
4694 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4695 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4696 SILC_NOTIFY_TYPE_KICKED, 3,
4697 target_idp, target_idp_len,
4698 comment, comment ? strlen(comment) : 0,
4699 idp->data, idp->len);
4700 silc_buffer_free(idp);
4702 /* Remove the client from the channel. If the channel does not exist
4703 after removing the client then the client kicked itself off the channel
4704 and we don't have to send anything after that. */
4705 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4706 target_client, FALSE))
4709 /* Send KICKED notify to primary route */
4710 if (!server->standalone)
4711 silc_server_send_notify_kicked(server, server->router->connection,
4712 server->server_type == SILC_ROUTER ?
4713 TRUE : FALSE, channel,
4714 target_client->id, client->id, comment);
4716 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4717 /* Re-generate channel key */
4718 if (!silc_server_create_channel_key(server, channel, 0))
4721 /* Send the channel key to the channel. The key of course is not sent
4722 to the client who was kicked off the channel. */
4723 silc_server_send_channel_key(server, target_client->connection, channel,
4724 server->server_type == SILC_ROUTER ?
4725 FALSE : !server->standalone);
4729 silc_server_command_free(cmd);
4732 /* Server side of OPER command. Client uses this comand to obtain server
4733 operator privileges to this server/router. */
4735 SILC_SERVER_CMD_FUNC(oper)
4737 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4738 SilcServer server = cmd->server;
4739 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4740 unsigned char *username, *auth;
4742 SilcServerConfigAdmin *admin;
4743 SilcIDListData idata = (SilcIDListData)client;
4744 bool result = FALSE;
4745 SilcPublicKey cached_key;
4747 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4749 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4752 /* Get the username */
4753 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4755 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4756 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4761 /* Get the admin configuration */
4762 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4763 username, client->nickname);
4765 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4766 username, client->nickname);
4768 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4769 SILC_STATUS_ERR_AUTH_FAILED,
4775 /* Get the authentication payload */
4776 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4778 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4779 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4784 /* Verify the authentication data. If both passphrase and public key
4785 is set then try both of them. */
4786 if (admin->passphrase)
4787 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4788 admin->passphrase, admin->passphrase_len,
4789 idata->hash, client->id, SILC_ID_CLIENT);
4790 if (!result && admin->publickeys) {
4791 cached_key = silc_server_get_public_key(server, admin->publickeys);
4794 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4795 cached_key, 0, idata->hash,
4796 client->id, SILC_ID_CLIENT);
4799 /* Authentication failed */
4800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4801 SILC_STATUS_ERR_AUTH_FAILED,
4806 /* Client is now server operator */
4807 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4809 /* Update statistics */
4810 if (client->connection)
4811 server->stat.my_server_ops++;
4812 if (server->server_type == SILC_ROUTER)
4813 server->stat.server_ops++;
4815 /* Send UMODE change to primary router */
4816 if (!server->standalone)
4817 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4818 client->id, client->mode);
4820 /* Check if anyone is watching this nickname */
4821 if (server->server_type == SILC_ROUTER)
4822 silc_server_check_watcher_list(server, client, NULL,
4823 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4825 /* Send reply to the sender */
4826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4830 silc_server_command_free(cmd);
4833 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4835 QuitInternal q = (QuitInternal)context;
4836 SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4838 /* If there is pending outgoing data for the client then purge it
4839 to the network before closing connection. */
4840 silc_server_packet_queue_purge(q->server, q->sock);
4842 /* Close the connection on our side */
4843 client->router = NULL;
4844 client->connection = NULL;
4845 q->sock->user_data = NULL;
4846 silc_server_close_connection(q->server, q->sock);
4851 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4853 QuitInternal q = (QuitInternal)context;
4854 SilcClientEntry client = (SilcClientEntry)q->sock;
4856 SILC_LOG_DEBUG(("Start"));
4858 if (client->mode & SILC_UMODE_DETACHED)
4859 silc_server_free_client_data(q->server, NULL, client, TRUE,
4864 /* Server side of DETACH command. Detached the client from the network
4865 by closing the connection but preserving the session. */
4867 SILC_SERVER_CMD_FUNC(detach)
4869 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4870 SilcServer server = cmd->server;
4871 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4874 if (server->config->detach_disabled) {
4875 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4876 SILC_STATUS_ERR_UNKNOWN_COMMAND,
4881 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4884 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4886 /* Send the user mode notify to notify that client is detached */
4887 client->mode |= SILC_UMODE_DETACHED;
4888 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4889 if (!server->standalone)
4890 silc_server_send_notify_umode(server, server->router->connection,
4891 server->server_type == SILC_SERVER ?
4892 FALSE : TRUE, client->id, client->mode);
4894 /* Check if anyone is watching this nickname */
4895 if (server->server_type == SILC_ROUTER)
4896 silc_server_check_watcher_list(server, client, NULL,
4897 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4899 q = silc_calloc(1, sizeof(*q));
4901 q->sock = cmd->sock;
4902 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4903 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4905 if (server->config->detach_timeout) {
4906 q = silc_calloc(1, sizeof(*q));
4908 q->sock = (void *)client;
4909 silc_schedule_task_add(server->schedule, 0,
4910 silc_server_command_detach_timeout,
4911 q, server->config->detach_timeout * 60,
4912 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4915 /* Send reply to the sender */
4916 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4920 silc_server_command_free(cmd);
4923 /* Server side of WATCH command. */
4925 SILC_SERVER_CMD_FUNC(watch)
4927 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4928 SilcServer server = cmd->server;
4929 char *add_nick, *del_nick;
4930 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
4932 unsigned char hash[16], *tmp;
4933 SilcClientEntry client;
4934 SilcClientID *client_id = NULL;
4936 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4938 if (server->server_type == SILC_SERVER && !server->standalone) {
4939 if (!cmd->pending) {
4940 /* Send the command to router */
4942 SilcUInt16 old_ident;
4944 old_ident = silc_command_get_ident(cmd->payload);
4945 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4946 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4948 silc_server_packet_send(server, server->router->connection,
4949 SILC_PACKET_COMMAND, cmd->packet->flags,
4950 tmpbuf->data, tmpbuf->len, TRUE);
4952 /* Reprocess this packet after received reply from router */
4953 silc_server_command_pending(server, SILC_COMMAND_WATCH,
4954 silc_command_get_ident(cmd->payload),
4955 silc_server_command_watch,
4956 silc_server_command_dup(cmd));
4957 cmd->pending = TRUE;
4958 silc_command_set_ident(cmd->payload, old_ident);
4959 silc_buffer_free(tmpbuf);
4960 } else if (context2) {
4961 /* Received reply from router, just send same data to the client. */
4962 SilcServerCommandReplyContext reply = context2;
4964 silc_command_get_status(reply->payload, &status, NULL);
4965 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
4972 /* We are router and keep the watch list for local cell */
4974 /* Get the client ID */
4975 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4977 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4978 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4982 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4985 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4990 /* Get the client entry which must be in local list */
4991 client = silc_idlist_find_client_by_id(server->local_list,
4992 client_id, TRUE, NULL);
4994 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4995 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5001 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5002 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5003 if (!add_nick && !del_nick) {
5004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5005 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5010 if (add_nick && add_nick_len > 128)
5011 add_nick[128] = '\0';
5012 if (del_nick && del_nick_len > 128)
5013 del_nick[128] = '\0';
5015 memset(nick, 0, sizeof(nick));
5017 /* Add new nickname to be watched in our cell */
5019 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5021 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5025 /* Hash the nick, we have the hash saved, not nicks because we can
5026 do one to one mapping to the nick from Client ID hash this way. */
5027 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5028 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5030 /* Check whether this client is already watching this nickname */
5031 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5033 /* Nickname is alredy being watched for this client */
5034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5035 SILC_STATUS_ERR_NICKNAME_IN_USE,
5040 /* Get the nickname from the watcher list and use the same key in
5041 new entries as well. If key doesn't exist then create it. */
5042 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5043 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5045 /* Add the client to the watcher list with the specified nickname hash. */
5046 silc_hash_table_add(server->watcher_list, tmp, client);
5049 /* Delete nickname from watch list */
5051 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5053 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5057 /* Hash the nick, we have the hash saved, not nicks because we can
5058 do one to one mapping to the nick from Client ID hash this way. */
5059 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5060 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5062 /* Check that this client is watching for this nickname */
5063 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5064 client, (void **)&tmp)) {
5065 /* Nickname is alredy being watched for this client */
5066 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5067 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5071 /* Delete the nickname from the watcher list. */
5072 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5074 /* Now check whether there still exists entries with this key, if not
5075 then free the key to not leak memory. */
5076 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5080 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5084 silc_free(client_id);
5085 silc_server_command_free(cmd);
5088 /* Server side of SILCOPER command. Client uses this comand to obtain router
5089 operator privileges to this router. */
5091 SILC_SERVER_CMD_FUNC(silcoper)
5093 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5094 SilcServer server = cmd->server;
5095 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5096 unsigned char *username, *auth;
5098 SilcServerConfigAdmin *admin;
5099 SilcIDListData idata = (SilcIDListData)client;
5100 bool result = FALSE;
5101 SilcPublicKey cached_key;
5103 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5105 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5108 if (server->server_type != SILC_ROUTER) {
5109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5110 SILC_STATUS_ERR_AUTH_FAILED, 0);
5114 /* Get the username */
5115 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5117 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5118 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5123 /* Get the admin configuration */
5124 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5125 username, client->nickname);
5127 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5128 username, client->nickname);
5130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5131 SILC_STATUS_ERR_AUTH_FAILED, 0);
5136 /* Get the authentication payload */
5137 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5139 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5140 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5145 /* Verify the authentication data. If both passphrase and public key
5146 is set then try both of them. */
5147 if (admin->passphrase)
5148 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5149 admin->passphrase, admin->passphrase_len,
5150 idata->hash, client->id, SILC_ID_CLIENT);
5151 if (!result && admin->publickeys) {
5152 cached_key = silc_server_get_public_key(server, admin->publickeys);
5155 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5156 cached_key, 0, idata->hash,
5157 client->id, SILC_ID_CLIENT);
5160 /* Authentication failed */
5161 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5162 SILC_STATUS_ERR_AUTH_FAILED, 0);
5166 /* Client is now router operator */
5167 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5169 /* Update statistics */
5170 if (client->connection)
5171 server->stat.my_router_ops++;
5172 if (server->server_type == SILC_ROUTER)
5173 server->stat.router_ops++;
5175 /* Send UMODE change to primary router */
5176 if (!server->standalone)
5177 silc_server_send_notify_umode(server, server->router->connection, TRUE,
5178 client->id, client->mode);
5180 /* Check if anyone is watching this nickname */
5181 if (server->server_type == SILC_ROUTER)
5182 silc_server_check_watcher_list(server, client, NULL,
5183 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5185 /* Send reply to the sender */
5186 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5190 silc_server_command_free(cmd);
5193 /* Server side of command BAN. This is used to manage the ban list of the
5194 channel. To add clients and remove clients from the ban list. */
5196 SILC_SERVER_CMD_FUNC(ban)
5198 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5199 SilcServer server = cmd->server;
5200 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5202 SilcChannelEntry channel;
5203 SilcChannelClientEntry chl;
5204 SilcChannelID *channel_id = NULL;
5205 unsigned char *id, *add, *del;
5206 SilcUInt32 id_len, tmp_len;
5207 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5209 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5212 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5214 /* Get Channel ID */
5215 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5217 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5219 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5220 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5225 /* Get channel entry. The server must know about the channel since the
5226 client is expected to be on the channel. */
5227 channel = silc_idlist_find_channel_by_id(server->local_list,
5230 channel = silc_idlist_find_channel_by_id(server->global_list,
5233 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5234 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5240 /* Check whether this client is on the channel */
5241 if (!silc_server_client_on_channel(client, channel, &chl)) {
5242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5243 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5247 /* The client must be at least channel operator. */
5248 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5250 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5254 /* Get the new ban and add it to the ban list */
5255 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5257 if (!channel->ban_list)
5258 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5260 channel->ban_list = silc_realloc(channel->ban_list,
5261 sizeof(*channel->ban_list) *
5263 strlen(channel->ban_list) + 2));
5264 if (add[tmp_len - 1] == ',')
5265 add[tmp_len - 1] = '\0';
5267 strncat(channel->ban_list, add, tmp_len);
5268 strncat(channel->ban_list, ",", 1);
5271 /* Get the ban to be removed and remove it from the list */
5272 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5273 if (del && channel->ban_list) {
5274 char *start, *end, *n;
5276 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5277 silc_free(channel->ban_list);
5278 channel->ban_list = NULL;
5280 start = strstr(channel->ban_list, del);
5281 if (start && strlen(start) >= tmp_len) {
5282 end = start + tmp_len;
5283 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5284 strncat(n, channel->ban_list, start - channel->ban_list);
5285 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5287 silc_free(channel->ban_list);
5288 channel->ban_list = n;
5293 /* Send the BAN notify type to our primary router. */
5294 if (!server->standalone && (add || del))
5295 silc_server_send_notify_ban(server, server->router->connection,
5296 server->server_type == SILC_ROUTER ?
5297 TRUE : FALSE, channel, add, del);
5299 /* Send the reply back to the client */
5301 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5302 SILC_STATUS_OK, 0, ident, 2,
5304 3, channel->ban_list,
5306 strlen(channel->ban_list) -1 : 0);
5307 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5308 packet->data, packet->len, FALSE);
5310 silc_buffer_free(packet);
5313 silc_free(channel_id);
5314 silc_server_command_free(cmd);
5317 /* Server side command of LEAVE. Removes client from a channel. */
5319 SILC_SERVER_CMD_FUNC(leave)
5321 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5322 SilcServer server = cmd->server;
5323 SilcSocketConnection sock = cmd->sock;
5324 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5325 SilcChannelID *id = NULL;
5326 SilcChannelEntry channel;
5330 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5332 /* Get Channel ID */
5333 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5336 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5339 id = silc_id_payload_parse_id(tmp, len, NULL);
5341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5342 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5346 /* Get channel entry */
5347 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5349 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5351 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5352 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5358 /* Check whether this client is on the channel */
5359 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5360 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5361 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5365 /* Notify routers that they should remove this client from their list
5366 of clients on the channel. Send LEAVE notify type. */
5367 if (!server->standalone)
5368 silc_server_send_notify_leave(server, server->router->connection,
5369 server->server_type == SILC_ROUTER ?
5370 TRUE : FALSE, channel, id_entry->id);
5372 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5373 SILC_STATUS_OK, 0, 2, tmp, len);
5375 /* Remove client from channel */
5376 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5378 /* If the channel does not exist anymore we won't send anything */
5381 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5382 /* Re-generate channel key */
5383 if (!silc_server_create_channel_key(server, channel, 0))
5386 /* Send the channel key */
5387 silc_server_send_channel_key(server, NULL, channel,
5388 server->server_type == SILC_ROUTER ?
5389 FALSE : !server->standalone);
5394 silc_server_command_free(cmd);
5397 /* Server side of command USERS. Resolves clients and their USERS currently
5398 joined on the requested channel. The list of Client ID's and their modes
5399 on the channel is sent back. */
5401 SILC_SERVER_CMD_FUNC(users)
5403 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5404 SilcServer server = cmd->server;
5405 SilcChannelEntry channel;
5406 SilcChannelID *id = NULL;
5407 SilcBuffer packet, idp;
5408 unsigned char *channel_id;
5409 SilcUInt32 channel_id_len;
5410 SilcBuffer client_id_list;
5411 SilcBuffer client_mode_list;
5412 unsigned char lc[4];
5413 SilcUInt32 list_count = 0;
5414 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5417 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5419 /* Get Channel ID */
5420 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5422 /* Get channel name */
5423 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5425 if (!channel_id && !channel_name) {
5426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5427 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5432 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5435 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5440 /* If we are server and we don't know about this channel we will send
5441 the command to our router. If we know about the channel then we also
5442 have the list of users already. */
5444 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5446 channel = silc_idlist_find_channel_by_name(server->local_list,
5447 channel_name, NULL);
5449 if (!channel || channel->disabled || !channel->users_resolved) {
5450 if (server->server_type != SILC_ROUTER && !server->standalone &&
5454 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5455 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5457 /* Send USERS command */
5458 silc_server_packet_send(server, server->router->connection,
5459 SILC_PACKET_COMMAND, cmd->packet->flags,
5460 tmpbuf->data, tmpbuf->len, TRUE);
5462 /* Reprocess this packet after received reply */
5463 silc_server_command_pending(server, SILC_COMMAND_USERS,
5464 silc_command_get_ident(cmd->payload),
5465 silc_server_command_users,
5466 silc_server_command_dup(cmd));
5467 cmd->pending = TRUE;
5468 silc_command_set_ident(cmd->payload, ident);
5469 silc_buffer_free(tmpbuf);
5474 /* Check the global list as well. */
5476 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5478 channel = silc_idlist_find_channel_by_name(server->global_list,
5479 channel_name, NULL);
5481 /* Channel really does not exist */
5482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5483 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5489 /* If the channel is private or secret do not send anything, unless the
5490 user requesting this command is on the channel or is server */
5491 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5492 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5493 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5496 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5501 /* Get the users list */
5502 silc_server_get_users_on_channel(server, channel, &client_id_list,
5503 &client_mode_list, &list_count);
5506 SILC_PUT32_MSB(list_count, lc);
5509 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5510 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5511 SILC_STATUS_OK, 0, ident, 4,
5512 2, idp->data, idp->len,
5514 4, client_id_list->data,
5515 client_id_list->len,
5516 5, client_mode_list->data,
5517 client_mode_list->len);
5518 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5519 packet->data, packet->len, FALSE);
5521 silc_buffer_free(idp);
5522 silc_buffer_free(packet);
5523 silc_buffer_free(client_id_list);
5524 silc_buffer_free(client_mode_list);
5528 silc_server_command_free(cmd);
5531 /* Server side of command GETKEY. This fetches the client's public key
5532 from the server where to the client is connected. */
5534 SILC_SERVER_CMD_FUNC(getkey)
5536 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5537 SilcServer server = cmd->server;
5539 SilcClientEntry client;
5540 SilcServerEntry server_entry;
5541 SilcClientID *client_id = NULL;
5542 SilcServerID *server_id = NULL;
5543 SilcIDPayload idp = NULL;
5544 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5545 unsigned char *tmp, *pkdata;
5546 SilcUInt32 tmp_len, pklen;
5547 SilcBuffer pk = NULL;
5549 SilcPublicKey public_key;
5551 SILC_LOG_DEBUG(("Start"));
5553 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5555 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5556 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5560 idp = silc_id_payload_parse(tmp, tmp_len);
5562 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5563 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5568 id_type = silc_id_payload_get_type(idp);
5569 if (id_type == SILC_ID_CLIENT) {
5570 client_id = silc_id_payload_get_id(idp);
5572 /* If the client is not found from local list there is no chance it
5573 would be locally connected client so send the command further. */
5574 client = silc_idlist_find_client_by_id(server->local_list,
5575 client_id, TRUE, NULL);
5577 client = silc_idlist_find_client_by_id(server->global_list,
5578 client_id, TRUE, NULL);
5580 if ((!client && !cmd->pending && !server->standalone) ||
5581 (client && !client->connection && !cmd->pending &&
5582 !(client->mode & SILC_UMODE_DETACHED)) ||
5583 (client && !client->data.public_key && !cmd->pending)) {
5585 SilcUInt16 old_ident;
5586 SilcSocketConnection dest_sock;
5588 dest_sock = silc_server_get_client_route(server, NULL, 0,
5589 client_id, NULL, NULL);
5593 old_ident = silc_command_get_ident(cmd->payload);
5594 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5595 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5597 silc_server_packet_send(server, dest_sock,
5598 SILC_PACKET_COMMAND, cmd->packet->flags,
5599 tmpbuf->data, tmpbuf->len, TRUE);
5601 /* Reprocess this packet after received reply from router */
5602 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5603 silc_command_get_ident(cmd->payload),
5604 silc_server_command_getkey,
5605 silc_server_command_dup(cmd));
5606 cmd->pending = TRUE;
5607 silc_command_set_ident(cmd->payload, old_ident);
5608 silc_buffer_free(tmpbuf);
5613 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5614 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5619 /* The client is locally connected, just get the public key and
5620 send it back. If they key does not exist then do not send it,
5621 send just OK reply */
5622 public_key = client->data.public_key;
5627 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5628 pk = silc_buffer_alloc(4 + tmp_len);
5629 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5630 silc_buffer_format(pk,
5631 SILC_STR_UI_SHORT(tmp_len),
5632 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5633 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5639 } else if (id_type == SILC_ID_SERVER) {
5640 server_id = silc_id_payload_get_id(idp);
5642 /* If the server is not found from local list there is no chance it
5643 would be locally connected server so send the command further. */
5644 server_entry = silc_idlist_find_server_by_id(server->local_list,
5645 server_id, TRUE, NULL);
5647 server_entry = silc_idlist_find_server_by_id(server->global_list,
5648 server_id, TRUE, NULL);
5650 if (server_entry != server->id_entry &&
5651 ((!server_entry && !cmd->pending && !server->standalone) ||
5652 (server_entry && !server_entry->connection && !cmd->pending &&
5653 !server->standalone) ||
5654 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5655 !server->standalone))) {
5657 SilcUInt16 old_ident;
5659 old_ident = silc_command_get_ident(cmd->payload);
5660 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5661 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5663 silc_server_packet_send(server, server->router->connection,
5664 SILC_PACKET_COMMAND, cmd->packet->flags,
5665 tmpbuf->data, tmpbuf->len, TRUE);
5667 /* Reprocess this packet after received reply from router */
5668 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5669 silc_command_get_ident(cmd->payload),
5670 silc_server_command_getkey,
5671 silc_server_command_dup(cmd));
5672 cmd->pending = TRUE;
5673 silc_command_set_ident(cmd->payload, old_ident);
5674 silc_buffer_free(tmpbuf);
5678 if (!server_entry) {
5679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5680 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5685 /* If they key does not exist then do not send it, send just OK reply */
5686 public_key = (!server_entry->data.public_key ?
5687 (server_entry == server->id_entry ? server->public_key :
5688 NULL) : server_entry->data.public_key);
5693 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5694 pk = silc_buffer_alloc(4 + tmp_len);
5695 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5696 silc_buffer_format(pk,
5697 SILC_STR_UI_SHORT(tmp_len),
5698 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5699 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5709 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5710 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5711 SILC_STATUS_OK, 0, ident,
5715 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5716 packet->data, packet->len, FALSE);
5717 silc_buffer_free(packet);
5720 silc_buffer_free(pk);
5724 silc_id_payload_free(idp);
5725 silc_free(client_id);
5726 silc_free(server_id);
5727 silc_server_command_free(cmd);
5731 /* Private range commands, specific to this implementation */
5733 /* Server side command of CONNECT. Connects us to the specified remote
5734 server or router. */
5736 SILC_SERVER_CMD_FUNC(connect)
5738 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5739 SilcServer server = cmd->server;
5740 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5741 unsigned char *tmp, *host;
5743 SilcUInt32 port = SILC_PORT;
5745 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5747 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5750 /* Check whether client has the permissions. */
5751 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5752 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5754 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5758 if (server->server_type == SILC_ROUTER &&
5759 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5760 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5761 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5765 /* Get the remote server */
5766 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5768 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5769 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5775 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5777 SILC_GET32_MSB(port, tmp);
5779 /* Create the connection. It is done with timeout and is async. */
5780 silc_server_create_connection(server, host, port);
5782 /* Send reply to the sender */
5783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5787 silc_server_command_free(cmd);
5790 /* Server side command of CLOSE. Closes connection to a specified server. */
5792 SILC_SERVER_CMD_FUNC(close)
5794 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5795 SilcServer server = cmd->server;
5796 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5797 SilcServerEntry server_entry;
5798 SilcSocketConnection sock;
5801 unsigned char *name;
5802 SilcUInt32 port = SILC_PORT;
5804 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5806 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5809 /* Check whether client has the permissions. */
5810 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5811 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5813 SILC_STATUS_ERR_NO_SERVER_PRIV,
5818 /* Get the remote server */
5819 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5822 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5828 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5830 SILC_GET32_MSB(port, tmp);
5832 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5833 name, port, FALSE, NULL);
5835 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5836 name, port, FALSE, NULL);
5837 if (!server_entry) {
5838 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5839 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5843 /* Send reply to the sender */
5844 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5847 /* Close the connection to the server */
5848 sock = (SilcSocketConnection)server_entry->connection;
5850 /* If we shutdown primary router connection manually then don't trigger
5851 any reconnect or backup router connections, by setting the router
5853 if (server->router == server_entry) {
5854 server->id_entry->router = NULL;
5855 server->router = NULL;
5856 server->standalone = TRUE;
5858 silc_server_free_sock_user_data(server, sock, NULL);
5859 silc_server_close_connection(server, sock);
5862 silc_server_command_free(cmd);
5865 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5866 active connections. */
5868 SILC_SERVER_CMD_FUNC(shutdown)
5870 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5871 SilcServer server = cmd->server;
5872 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5874 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5876 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5879 /* Check whether client has the permission. */
5880 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5881 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5883 SILC_STATUS_ERR_NO_SERVER_PRIV,
5888 /* Send reply to the sender */
5889 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5892 /* Then, gracefully, or not, bring the server down. */
5893 silc_server_stop(server);
5897 silc_server_command_free(cmd);