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 SILC_LOG_DEBUG(("Start"));
192 /* Allocate command context. This must be free'd by the
193 command routine receiving it. */
194 ctx = silc_server_command_alloc();
195 ctx->server = server;
196 ctx->sock = silc_socket_dup(sock);
197 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
199 /* Parse the command payload in the packet */
200 ctx->payload = silc_command_payload_parse(packet->buffer->data,
201 packet->buffer->len);
203 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
204 silc_packet_context_free(packet);
205 silc_socket_free(ctx->sock);
209 ctx->args = silc_command_get_args(ctx->payload);
211 /* Get the command */
212 command = silc_command_get(ctx->payload);
213 for (cmd = silc_command_list; cmd->cb; cmd++)
214 if (cmd->cmd == command)
217 if (!cmd || !cmd->cb) {
218 silc_server_command_send_status_reply(ctx, command,
219 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
220 silc_server_command_free(ctx);
224 /* Execute client's commands always with timeout. Normally they are
225 executed with zero (0) timeout but if client is sending command more
226 frequently than once in 2 seconds, then the timeout may be 0 to 2
228 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
229 SilcClientEntry client = (SilcClientEntry)sock->user_data;
230 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
236 if (client->last_command && (time(NULL) - client->last_command) < 2) {
237 client->fast_command++;
240 if (client->fast_command - 2 <= 0)
241 client->fast_command = 0;
243 client->fast_command -= 2;
247 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
248 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
249 silc_schedule_task_add(server->schedule, sock->sock,
250 silc_server_command_process_timeout, timeout,
251 (client->fast_command < 3 ? 0 :
252 2 - (time(NULL) - client->last_command)),
253 (client->fast_command < 3 ? 200000 : 0),
254 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
256 silc_schedule_task_add(server->schedule, sock->sock,
257 silc_server_command_process_timeout, timeout,
258 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
262 /* Execute for server */
264 if (!(cmd->flags & SILC_CF_REG))
266 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
269 silc_server_command_free(ctx);
272 /* Allocate Command Context */
274 SilcServerCommandContext silc_server_command_alloc()
276 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
281 /* Free's the command context allocated before executing the command */
283 void silc_server_command_free(SilcServerCommandContext ctx)
286 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
288 if (ctx->users < 1) {
290 silc_command_payload_free(ctx->payload);
292 silc_packet_context_free(ctx->packet);
294 silc_socket_free(ctx->sock); /* Decrease reference counter */
299 /* Duplicate Command Context by adding reference counter. The context won't
300 be free'd untill it hits zero. */
302 SilcServerCommandContext
303 silc_server_command_dup(SilcServerCommandContext ctx)
306 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
311 /* Add new pending command to be executed when reply to a command has been
312 received. The `reply_cmd' is the command that will call the `callback'
313 with `context' when reply has been received. It can be SILC_COMMAND_NONE
314 to match any command with the `ident'. If `ident' is non-zero
315 the `callback' will be executed when received reply with command
316 identifier `ident'. If there already exists pending command for the
317 specified command, ident, callback and context this function has no
320 bool silc_server_command_pending(SilcServer server,
321 SilcCommand reply_cmd,
323 SilcCommandCb callback,
326 SilcServerCommandPending *reply;
328 /* Check whether identical pending already exists for same command,
329 ident, callback and callback context. If it does then it would be
330 error to register it again. */
331 silc_dlist_start(server->pending_commands);
332 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
333 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
334 reply->callback == callback && reply->context == context)
338 reply = silc_calloc(1, sizeof(*reply));
339 reply->reply_cmd = reply_cmd;
340 reply->ident = ident;
341 reply->context = context;
342 reply->callback = callback;
343 silc_dlist_add(server->pending_commands, reply);
348 /* Deletes pending command by reply command type. */
350 void silc_server_command_pending_del(SilcServer server,
351 SilcCommand reply_cmd,
354 SilcServerCommandPending *r;
356 silc_dlist_start(server->pending_commands);
357 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
358 if (r->reply_cmd == reply_cmd && r->ident == ident) {
359 silc_dlist_del(server->pending_commands, r);
365 /* Checks for pending commands and marks callbacks to be called from
366 the command reply function. Returns TRUE if there were pending command. */
368 SilcServerCommandPendingCallbacks
369 silc_server_command_pending_check(SilcServer server,
370 SilcServerCommandReplyContext ctx,
373 SilcUInt32 *callbacks_count)
375 SilcServerCommandPending *r;
376 SilcServerCommandPendingCallbacks callbacks = NULL;
379 silc_dlist_start(server->pending_commands);
380 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
381 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
382 && r->ident == ident) {
383 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
384 callbacks[i].context = r->context;
385 callbacks[i].callback = r->callback;
391 *callbacks_count = i;
395 /* Sends simple status message as command reply packet */
398 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
405 SILC_LOG_DEBUG(("Sending command status %d", status));
408 silc_command_reply_payload_encode_va(command, status, error,
409 silc_command_get_ident(cmd->payload),
411 silc_server_packet_send(cmd->server, cmd->sock,
412 SILC_PACKET_COMMAND_REPLY, 0,
413 buffer->data, buffer->len, FALSE);
414 silc_buffer_free(buffer);
417 /* Sends command status reply with one extra argument. The argument
418 type must be sent as argument. */
421 silc_server_command_send_status_data(SilcServerCommandContext cmd,
426 const unsigned char *arg,
431 SILC_LOG_DEBUG(("Sending command status %d", status));
434 silc_command_reply_payload_encode_va(command, status, 0,
435 silc_command_get_ident(cmd->payload),
436 1, arg_type, arg, arg_len);
437 silc_server_packet_send(cmd->server, cmd->sock,
438 SILC_PACKET_COMMAND_REPLY, 0,
439 buffer->data, buffer->len, FALSE);
440 silc_buffer_free(buffer);
443 /* This function can be called to check whether in the command reply
444 an error occurred. This function has no effect if this is called
445 when the command function was not called as pending command callback.
446 This returns TRUE if error had occurred. */
449 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
450 SilcServerCommandReplyContext cmdr,
453 if (!cmd->pending || !cmdr)
456 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
459 /* Send the same command reply payload */
460 silc_command_set_ident(cmdr->payload,
461 silc_command_get_ident(cmd->payload));
462 buffer = silc_command_payload_encode_payload(cmdr->payload);
463 silc_server_packet_send(cmd->server, cmd->sock,
464 SILC_PACKET_COMMAND_REPLY, 0,
465 buffer->data, buffer->len, FALSE);
466 silc_buffer_free(buffer);
473 /******************************************************************************
477 ******************************************************************************/
486 #define ADD_ERROR(errptr, errptr_count, _id, _id_type, _index, _status) \
488 errptr = silc_realloc(errptr, sizeof(*errptr) * (errptr_count + 1)); \
491 errptr[errptr_count].id = _id; \
492 errptr[errptr_count].id_type = _id_type; \
493 errptr[errptr_count].index = _index; \
494 errptr[errptr_count].error = _status; \
499 silc_server_command_whois_parse(SilcServerCommandContext cmd,
500 SilcClientID ***client_id,
501 SilcUInt32 *client_id_count,
505 ResolveError *error_client,
506 SilcUInt32 *error_client_count)
510 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
514 /* If client ID is in the command it must be used instead of nickname */
515 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
517 /* No ID, get the nickname@server string and parse it. */
518 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
520 silc_parse_userfqdn(tmp, nickname, server_name);
522 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
523 SILC_STATUS_ERR_BAD_NICKNAME, 0);
527 /* Command includes ID, we must use that. Take all ID's from the
529 for (k = 0, i = 0; i < argc; i++) {
530 tmp = silc_argument_get_arg_type(cmd->args, i + 4, &len);
533 id = silc_id_payload_parse_id(tmp, len, NULL);
535 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
536 (*client_id_count + 1));
537 (*client_id)[k] = id;
538 (*client_id_count)++;
541 ADD_ERROR((*error_client), (*error_client_count), NULL, 0, i + 4,
542 SILC_STATUS_ERR_BAD_CLIENT_ID);
547 /* Get the max count of reply messages allowed */
548 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
550 SILC_GET32_MSB(*count, tmp);
557 /* Resolve context used by both WHOIS and IDENTIFY commands */
559 SilcServerEntry router;
561 unsigned char **res_argv;
562 SilcUInt32 *res_argv_lens;
563 SilcUInt32 *res_argv_types;
565 } *SilcServerResolveContext;
568 silc_server_command_whois_check(SilcServerCommandContext cmd,
569 SilcClientEntry *clients,
570 SilcUInt32 clients_count)
572 SilcServer server = cmd->server;
573 SilcClientEntry entry;
574 SilcServerResolveContext resolve = NULL, r = NULL;
575 SilcUInt32 resolve_count = 0;
579 SILC_LOG_DEBUG(("Start"));
581 for (i = 0; i < clients_count; i++) {
586 if ((entry->nickname && entry->username && entry->userinfo) ||
587 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
591 /* If we are normal server, and we've not resolved this client from
592 router and it is global client, we'll check whether it is on some
593 channel. If not then we cannot be sure about its validity, and
594 we'll resolve it from router. */
595 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
596 entry->connection || silc_hash_table_count(entry->channels))
600 /* We need to resolve this entry since it is not complete */
602 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
603 /* The entry is being resolved (and we are not the resolver) so attach
604 to the command reply and we're done with this one. */
605 silc_server_command_pending(server, SILC_COMMAND_NONE,
606 entry->resolve_cmd_ident,
607 silc_server_command_whois,
608 silc_server_command_dup(cmd));
611 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
612 /* We've resolved this and it still is not ready. We'll return
613 and are that this will be handled again after it is resolved. */
614 for (i = 0; i < resolve_count; i++) {
615 for (k = 0; k < r->res_argc; k++)
616 silc_free(r->res_argv[k]);
617 silc_free(r->res_argv);
618 silc_free(r->res_argv_lens);
619 silc_free(r->res_argv_types);
624 /* We'll resolve this client */
628 for (k = 0; k < resolve_count; k++) {
629 if (resolve[k].router == entry->router) {
636 resolve = silc_realloc(resolve, sizeof(*resolve) *
637 (resolve_count + 1));
638 r = &resolve[resolve_count];
639 memset(r, 0, sizeof(*r));
640 r->router = entry->router;
641 r->ident = ++server->cmd_ident;
645 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
647 r->res_argv_lens = silc_realloc(r->res_argv_lens,
648 sizeof(*r->res_argv_lens) *
650 r->res_argv_types = silc_realloc(r->res_argv_types,
651 sizeof(*r->res_argv_types) *
653 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
654 r->res_argv[r->res_argc] = silc_calloc(idp->len,
655 sizeof(**r->res_argv));
656 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
657 r->res_argv_lens[r->res_argc] = idp->len;
658 r->res_argv_types[r->res_argc] = r->res_argc + 4;
660 silc_buffer_free(idp);
662 entry->resolve_cmd_ident = r->ident;
663 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
664 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
669 /* Do the resolving */
670 for (i = 0; i < resolve_count; i++) {
675 /* Send WHOIS request. We send WHOIS since we're doing the requesting
676 now anyway so make it a good one. */
677 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
678 r->res_argc, r->res_argv,
682 silc_server_packet_send(server, r->router->connection,
683 SILC_PACKET_COMMAND, cmd->packet->flags,
684 res_cmd->data, res_cmd->len, FALSE);
686 /* Reprocess this packet after received reply */
687 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
689 silc_server_command_whois,
690 silc_server_command_dup(cmd));
693 silc_buffer_free(res_cmd);
694 for (k = 0; k < r->res_argc; k++)
695 silc_free(r->res_argv[k]);
696 silc_free(r->res_argv);
697 silc_free(r->res_argv_lens);
698 silc_free(r->res_argv_types);
707 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
708 SilcClientEntry *clients,
709 SilcUInt32 clients_count,
711 SilcUInt32 errors_count,
712 int count, const char *nickname,
713 SilcClientID **client_ids)
715 SilcServer server = cmd->server;
717 int i, k, valid_count = clients_count;
719 SilcBuffer packet, idp, channels, umode_list = NULL;
720 SilcClientEntry entry;
722 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
723 char nh[256], uh[256];
724 unsigned char idle[4], mode[4];
725 unsigned char *fingerprint;
726 SilcSocketConnection hsock;
729 /* Process only valid clients and ignore those that are not registered.
730 This is checked with nickname only because when resolved client IDs
731 we check that they are registered earlier. */
733 for (i = 0; i < clients_count; i++)
734 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
740 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
741 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
742 3, nickname, strlen(nickname));
747 /* Start processing found clients. */
748 status = SILC_STATUS_OK;
750 status = SILC_STATUS_LIST_START;
752 for (i = 0, k = 0; i < clients_count; i++) {
758 status = SILC_STATUS_LIST_ITEM;
759 if (valid_count > 1 && k == valid_count - 1 && !errors_count)
760 status = SILC_STATUS_LIST_END;
761 if (count && k - 1 == count)
762 status = SILC_STATUS_LIST_END;
764 /* Send WHOIS reply */
765 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
766 tmp = silc_argument_get_first_arg(cmd->args, NULL);
768 memset(uh, 0, sizeof(uh));
769 memset(nh, 0, sizeof(nh));
770 memset(idle, 0, sizeof(idle));
772 strncat(nh, entry->nickname, strlen(entry->nickname));
773 if (!strchr(entry->nickname, '@')) {
775 if (entry->servername) {
776 strncat(nh, entry->servername, strlen(entry->servername));
778 len = entry->router ? strlen(entry->router->server_name) :
779 strlen(server->server_name);
780 strncat(nh, entry->router ? entry->router->server_name :
781 server->server_name, len);
785 strncat(uh, entry->username, strlen(entry->username));
786 if (!strchr(entry->username, '@') && entry->connection) {
788 hsock = (SilcSocketConnection)entry->connection;
789 len = strlen(hsock->hostname);
790 strncat(uh, hsock->hostname, len);
793 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
794 channels = silc_server_get_client_channel_list(server, entry, FALSE,
797 channels = silc_server_get_client_channel_list(server, entry, TRUE,
800 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
801 fingerprint = entry->data.fingerprint;
805 SILC_PUT32_MSB(entry->mode, mode);
806 if (entry->connection)
807 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
810 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
812 2, idp->data, idp->len,
816 strlen(entry->userinfo),
817 6, channels ? channels->data : NULL,
818 channels ? channels->len : 0,
822 fingerprint ? 20 : 0,
823 10, umode_list ? umode_list->data :
824 NULL, umode_list ? umode_list->len :
827 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
828 0, packet->data, packet->len, FALSE);
830 silc_buffer_free(packet);
831 silc_buffer_free(idp);
833 silc_buffer_free(channels);
835 silc_buffer_free(umode_list);
839 if (status == SILC_STATUS_LIST_END)
844 /* Send error replies */
845 if (status == SILC_STATUS_OK && errors_count > 1)
846 status = SILC_STATUS_LIST_START;
849 for (i = 0, k = 0; i < errors_count; i++) {
851 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
855 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
859 status = SILC_STATUS_LIST_ITEM;
860 if (errors_count > 1 && k == errors_count - 1)
861 status = SILC_STATUS_LIST_END;
862 if (count && k - 1 == count)
863 status = SILC_STATUS_LIST_END;
866 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
867 (status == SILC_STATUS_OK ?
868 errors[i].error : status),
869 (status == SILC_STATUS_OK ?
870 0 : errors[i].error),
872 silc_buffer_free(idp);
875 if (status == SILC_STATUS_LIST_END)
882 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
884 SilcServer server = cmd->server;
886 SilcUInt16 old_ident;
888 old_ident = silc_command_get_ident(cmd->payload);
889 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
890 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
892 /* Send WHOIS command to our router */
893 silc_server_packet_send(server, (SilcSocketConnection)
894 server->router->connection,
895 SILC_PACKET_COMMAND, cmd->packet->flags,
896 tmpbuf->data, tmpbuf->len, TRUE);
898 /* Reprocess this packet after received reply from router */
899 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
900 silc_command_get_ident(cmd->payload),
901 silc_server_command_whois,
902 silc_server_command_dup(cmd));
904 silc_command_set_ident(cmd->payload, old_ident);
905 silc_buffer_free(tmpbuf);
909 silc_server_command_whois_process(SilcServerCommandContext cmd)
911 SilcServer server = cmd->server;
912 char *nick = NULL, *server_name = NULL;
914 SilcClientEntry *clients = NULL, entry;
915 SilcClientID **client_id = NULL;
916 SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
917 ResolveError error_client = NULL;
919 bool check_global = FALSE;
921 /* Parse the whois request */
922 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
923 &nick, &server_name, &count,
924 &error_client, &error_client_count))
927 /* Send the WHOIS request to the router only if it included nickname.
928 Since nicknames can be expanded into many clients we need to send it
929 to router. If the WHOIS included only client ID's we will check them
930 first locally since we just might have them. */
931 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
932 server->server_type == SILC_SERVER && !cmd->pending &&
933 !server->standalone) {
934 silc_server_command_whois_send_router(cmd);
939 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
941 else if (server->server_type != SILC_SERVER)
944 /* Get all clients matching that ID or nickname from local list */
945 if (client_id_count) {
946 /* Check all Client ID's received in the command packet */
947 for (i = 0; i < client_id_count; i++) {
948 entry = silc_idlist_find_client_by_id(server->local_list,
949 client_id[i], TRUE, NULL);
950 if (!entry && check_global)
951 entry = silc_idlist_find_client_by_id(server->global_list,
952 client_id[i], TRUE, NULL);
954 clients = silc_realloc(clients, sizeof(*clients) *
955 (clients_count + 1));
956 clients[clients_count++] = entry;
958 /* If we are normal server and did not send the request first to router
959 do it now, since we do not have the Client ID information. */
960 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
961 server->server_type == SILC_SERVER && !cmd->pending &&
962 !server->standalone) {
963 silc_server_command_whois_send_router(cmd);
968 ADD_ERROR(error_client, error_client_count, client_id[i],
969 SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
973 /* Find by nickname */
974 if (!silc_idlist_get_clients_by_hash(server->local_list,
975 nick, server->md5hash,
976 &clients, &clients_count))
977 silc_idlist_get_clients_by_nickname(server->local_list,
979 &clients, &clients_count);
981 if (!silc_idlist_get_clients_by_hash(server->global_list,
982 nick, server->md5hash,
983 &clients, &clients_count))
984 silc_idlist_get_clients_by_nickname(server->global_list,
986 &clients, &clients_count);
990 if (!clients && (client_id_count || nick)) {
991 /* If we are normal server and did not send the request first to router
992 do it now, since we do not have the information. */
993 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
994 server->server_type == SILC_SERVER && !cmd->pending &&
995 !server->standalone) {
996 silc_server_command_whois_send_router(cmd);
1001 /* Such client(s) really does not exist in the SILC network. */
1002 if (!client_id_count)
1003 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1004 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1005 3, nick, strlen(nick));
1007 silc_server_command_whois_send_reply(cmd, NULL, 0,
1008 error_client, error_client_count,
1013 /* Router always finds the client entry if it exists in the SILC network.
1014 However, it might be incomplete entry and does not include all the
1015 mandatory fields that WHOIS command reply requires. Check for these and
1016 make query from the server who owns the client if some fields are
1018 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
1023 /* Send the command reply */
1024 silc_server_command_whois_send_reply(cmd, clients, clients_count,
1025 error_client, error_client_count,
1026 count, nick, client_id);
1029 if (client_id_count) {
1030 for (i = 0; i < client_id_count; i++)
1031 silc_free(client_id[i]);
1032 silc_free(client_id);
1035 silc_free(error_client);
1037 silc_free(server_name);
1042 /* Server side of command WHOIS. Processes user's query and sends found
1043 results as command replies back to the client. */
1045 SILC_SERVER_CMD_FUNC(whois)
1047 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1050 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1052 ret = silc_server_command_whois_process(cmd);
1053 silc_server_command_free(cmd);
1056 /******************************************************************************
1060 ******************************************************************************/
1063 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1071 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1074 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1079 /* Get the nickname@server string and parse it. */
1080 silc_parse_userfqdn(tmp, nickname, server_name);
1082 /* Get the max count of reply messages allowed */
1083 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1085 SILC_GET32_MSB(*count, tmp);
1093 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1094 SilcClientEntry *clients,
1095 SilcUInt32 clients_count)
1097 SilcServer server = cmd->server;
1099 SilcClientEntry entry;
1101 for (i = 0; i < clients_count; i++) {
1104 if (!entry->nickname || !entry->username) {
1106 SilcUInt16 old_ident;
1111 old_ident = silc_command_get_ident(cmd->payload);
1112 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1113 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1115 /* Send WHOWAS command */
1116 silc_server_packet_send(server, entry->router->connection,
1117 SILC_PACKET_COMMAND, cmd->packet->flags,
1118 tmpbuf->data, tmpbuf->len, TRUE);
1120 /* Reprocess this packet after received reply */
1121 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1122 silc_command_get_ident(cmd->payload),
1123 silc_server_command_whowas,
1124 silc_server_command_dup(cmd));
1125 cmd->pending = TRUE;
1126 silc_command_set_ident(cmd->payload, old_ident);
1128 silc_buffer_free(tmpbuf);
1137 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1138 SilcClientEntry *clients,
1139 SilcUInt32 clients_count)
1141 SilcServer server = cmd->server;
1143 int i, k, count = 0, len;
1144 SilcBuffer packet, idp;
1145 SilcClientEntry entry = NULL;
1147 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1148 char nh[256], uh[256];
1151 status = SILC_STATUS_OK;
1153 /* Process only entries that are not registered anymore. */
1155 for (i = 0; i < clients_count; i++) {
1156 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1163 /* No valid entries found at all, just send error */
1164 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1165 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1166 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1167 3, tmp, tmp ? strlen(tmp) : 0);
1171 if (valid_count > 1)
1172 status = SILC_STATUS_LIST_START;
1174 for (i = 0, k = 0; i < clients_count; i++) {
1180 status = SILC_STATUS_LIST_ITEM;
1181 if (valid_count > 1 && k == valid_count - 1)
1182 status = SILC_STATUS_LIST_END;
1183 if (count && k - 1 == count)
1184 status = SILC_STATUS_LIST_END;
1186 /* Send WHOWAS reply */
1187 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1188 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1189 memset(uh, 0, sizeof(uh));
1190 memset(nh, 0, sizeof(nh));
1192 strncat(nh, entry->nickname, strlen(entry->nickname));
1193 if (!strchr(entry->nickname, '@')) {
1194 strncat(nh, "@", 1);
1195 if (entry->servername) {
1196 strncat(nh, entry->servername, strlen(entry->servername));
1198 len = entry->router ? strlen(entry->router->server_name) :
1199 strlen(server->server_name);
1200 strncat(nh, entry->router ? entry->router->server_name :
1201 server->server_name, len);
1205 strncat(uh, entry->username, strlen(entry->username));
1206 if (!strchr(entry->username, '@')) {
1207 strncat(uh, "@", 1);
1208 strcat(uh, "*private*");
1212 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1213 status, 0, ident, 4,
1214 2, idp->data, idp->len,
1219 strlen(entry->userinfo) : 0);
1220 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1221 0, packet->data, packet->len, FALSE);
1223 silc_buffer_free(packet);
1224 silc_buffer_free(idp);
1226 if (status == SILC_STATUS_LIST_END)
1233 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1235 SilcServer server = cmd->server;
1236 char *nick = NULL, *server_name = NULL;
1238 SilcClientEntry *clients = NULL;
1239 SilcUInt32 clients_count = 0;
1241 bool check_global = FALSE;
1243 /* Protocol dictates that we must always send the received WHOWAS request
1244 to our router if we are normal server, so let's do it now unless we
1245 are standalone. We will not send any replies to the client until we
1246 have received reply from the router. */
1247 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1248 server->server_type == SILC_SERVER && !cmd->pending &&
1249 !server->standalone) {
1251 SilcUInt16 old_ident;
1253 old_ident = silc_command_get_ident(cmd->payload);
1254 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1255 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1257 /* Send WHOWAS command to our router */
1258 silc_server_packet_send(server, (SilcSocketConnection)
1259 server->router->connection,
1260 SILC_PACKET_COMMAND, cmd->packet->flags,
1261 tmpbuf->data, tmpbuf->len, TRUE);
1263 /* Reprocess this packet after received reply from router */
1264 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1265 silc_command_get_ident(cmd->payload),
1266 silc_server_command_whowas,
1267 silc_server_command_dup(cmd));
1268 cmd->pending = TRUE;
1269 silc_command_set_ident(cmd->payload, old_ident);
1271 silc_buffer_free(tmpbuf);
1276 /* We are ready to process the command request. Let's search for the
1277 requested client and send reply to the requesting client. */
1279 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1280 check_global = TRUE;
1281 else if (server->server_type != SILC_SERVER)
1282 check_global = TRUE;
1284 /* Parse the whowas request */
1285 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1288 /* Get all clients matching that nickname from local list */
1289 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1291 &clients, &clients_count))
1292 silc_idlist_get_clients_by_hash(server->local_list,
1293 nick, server->md5hash,
1294 &clients, &clients_count);
1296 /* Check global list as well */
1298 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1300 &clients, &clients_count))
1301 silc_idlist_get_clients_by_hash(server->global_list,
1302 nick, server->md5hash,
1303 &clients, &clients_count);
1307 /* Such a client really does not exist in the SILC network. */
1308 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1309 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1310 3, nick, strlen(nick));
1314 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1319 /* Send the command reply to the client */
1320 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1325 silc_free(server_name);
1329 /* Server side of command WHOWAS. */
1331 SILC_SERVER_CMD_FUNC(whowas)
1333 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1336 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1338 ret = silc_server_command_whowas_process(cmd);
1339 silc_server_command_free(cmd);
1342 /******************************************************************************
1346 ******************************************************************************/
1349 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1351 SilcServer server = cmd->server;
1353 SilcUInt16 old_ident;
1355 old_ident = silc_command_get_ident(cmd->payload);
1356 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1357 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1359 /* Send IDENTIFY command to our router */
1360 silc_server_packet_send(server, (SilcSocketConnection)
1361 server->router->connection,
1362 SILC_PACKET_COMMAND, cmd->packet->flags,
1363 tmpbuf->data, tmpbuf->len, TRUE);
1365 /* Reprocess this packet after received reply from router */
1366 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1367 silc_command_get_ident(cmd->payload),
1368 silc_server_command_identify,
1369 silc_server_command_dup(cmd));
1370 cmd->pending = TRUE;
1371 silc_command_set_ident(cmd->payload, old_ident);
1372 silc_buffer_free(tmpbuf);
1376 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1377 SilcClientEntry **clients,
1378 SilcUInt32 *clients_count,
1379 SilcServerEntry **servers,
1380 SilcUInt32 *servers_count,
1381 SilcChannelEntry **channels,
1382 SilcUInt32 *channels_count,
1384 ResolveError *error_id,
1385 SilcUInt32 *error_id_count)
1387 SilcServer server = cmd->server;
1390 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1392 bool check_global = FALSE;
1396 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1397 check_global = TRUE;
1398 else if (server->server_type != SILC_SERVER)
1399 check_global = TRUE;
1401 /* If ID Payload is in the command it must be used instead of names */
1402 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1404 /* No ID, get the names. */
1406 /* If we are normal server and have not resolved information from
1407 router yet, do so now. */
1408 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1409 server->server_type == SILC_SERVER && !cmd->pending &&
1410 !server->standalone) {
1411 silc_server_command_identify_send_router(cmd);
1415 /* Try to get nickname@server. */
1416 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1419 char *nick_server = NULL;
1421 silc_parse_userfqdn(tmp, &nick, &nick_server);
1423 if (!silc_idlist_get_clients_by_hash(server->local_list,
1424 nick, server->md5hash,
1425 clients, clients_count))
1426 silc_idlist_get_clients_by_nickname(server->local_list,
1428 clients, clients_count);
1430 if (!silc_idlist_get_clients_by_hash(server->global_list,
1431 nick, server->md5hash,
1432 clients, clients_count))
1433 silc_idlist_get_clients_by_nickname(server->global_list,
1435 clients, clients_count);
1439 silc_free(nick_server);
1442 /* the nickname does not exist, send error reply */
1443 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1444 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1445 3, tmp, strlen(tmp));
1450 /* Try to get server name */
1451 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1453 entry = silc_idlist_find_server_by_name(server->local_list,
1455 if (!entry && check_global)
1456 entry = silc_idlist_find_server_by_name(server->global_list,
1459 *servers = silc_realloc(*servers, sizeof(**servers) *
1460 (*servers_count + 1));
1461 (*servers)[(*servers_count)++] = entry;
1465 /* the server does not exist, send error reply */
1466 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1467 SILC_STATUS_ERR_NO_SUCH_SERVER,
1468 0, 3, tmp, strlen(tmp));
1473 /* Try to get channel name */
1474 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1476 entry = silc_idlist_find_channel_by_name(server->local_list,
1478 if (!entry && check_global)
1479 entry = silc_idlist_find_channel_by_name(server->global_list,
1482 *channels = silc_realloc(*channels, sizeof(**channels) *
1483 (*channels_count + 1));
1484 (*channels)[(*channels_count)++] = entry;
1488 /* The channel does not exist, send error reply */
1489 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1490 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1491 0, 3, tmp, strlen(tmp));
1496 if (!(*clients) && !(*servers) && !(*channels)) {
1497 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1498 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1503 /* Command includes ID, we must use that. Also check whether the command
1504 has more than one ID set - take them all. */
1506 /* Take all ID's from the command packet */
1507 for (i = 0; i < argc; i++) {
1510 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1514 idp = silc_id_payload_parse(tmp, len);
1516 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1517 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1519 id = silc_id_payload_get_id(idp);
1520 switch (silc_id_payload_get_type(idp)) {
1522 case SILC_ID_CLIENT:
1523 entry = silc_idlist_find_client_by_id(server->local_list,
1525 if (!entry && check_global)
1526 entry = silc_idlist_find_client_by_id(server->global_list,
1529 *clients = silc_realloc(*clients, sizeof(**clients) *
1530 (*clients_count + 1));
1531 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1533 /* If we are normal server and have not resolved information from
1534 router yet, do so now. */
1535 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1536 server->server_type == SILC_SERVER && !cmd->pending &&
1537 !server->standalone) {
1538 silc_server_command_identify_send_router(cmd);
1539 silc_free(*clients);
1540 silc_free(*servers);
1541 silc_free(*channels);
1542 silc_free(*error_id);
1546 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1547 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1552 case SILC_ID_SERVER:
1553 entry = silc_idlist_find_server_by_id(server->local_list,
1555 if (!entry && check_global)
1556 entry = silc_idlist_find_server_by_id(server->global_list,
1559 *servers = silc_realloc(*servers, sizeof(**servers) *
1560 (*servers_count + 1));
1561 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1563 /* If we are normal server and have not resolved information from
1564 router yet, do so now. */
1565 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1566 server->server_type == SILC_SERVER && !cmd->pending &&
1567 !server->standalone) {
1568 silc_server_command_identify_send_router(cmd);
1569 silc_free(*clients);
1570 silc_free(*servers);
1571 silc_free(*channels);
1572 silc_free(*error_id);
1576 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1577 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
1581 case SILC_ID_CHANNEL:
1582 entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
1583 if (!entry && check_global)
1584 entry = silc_idlist_find_channel_by_id(server->global_list, id,
1587 *channels = silc_realloc(*channels, sizeof(**channels) *
1588 (*channels_count + 1));
1589 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1591 /* If we are normal server and have not resolved information from
1592 router yet, do so now. */
1593 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1594 server->server_type == SILC_SERVER && !cmd->pending &&
1595 !server->standalone) {
1596 silc_server_command_identify_send_router(cmd);
1597 silc_free(*clients);
1598 silc_free(*servers);
1599 silc_free(*channels);
1600 silc_free(*error_id);
1604 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1605 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
1614 /* Get the max count of reply messages allowed */
1615 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1617 SILC_GET32_MSB(*count, tmp);
1624 /* Checks that all mandatory fields in client entry are present. If not
1625 then send WHOIS request to the server who owns the client. We use
1626 WHOIS because we want to get as much information as possible at once. */
1629 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1630 SilcClientEntry *clients,
1631 SilcUInt32 clients_count)
1633 SilcServer server = cmd->server;
1634 SilcClientEntry entry;
1635 SilcServerResolveContext resolve = NULL, r = NULL;
1636 SilcUInt32 resolve_count = 0;
1640 for (i = 0; i < clients_count; i++) {
1645 if (entry->nickname ||
1646 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1650 /* If we are normal server, and we've not resolved this client from
1651 router and it is global client, we'll check whether it is on some
1652 channel. If not then we cannot be sure about its validity, and
1653 we'll resolve it from router. */
1654 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1655 entry->connection || silc_hash_table_count(entry->channels))
1659 /* We need to resolve this entry since it is not complete */
1661 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1662 /* The entry is being resolved (and we are not the resolver) so attach
1663 to the command reply and we're done with this one. */
1664 silc_server_command_pending(server, SILC_COMMAND_NONE,
1665 entry->resolve_cmd_ident,
1666 silc_server_command_identify,
1667 silc_server_command_dup(cmd));
1670 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1671 /* We've resolved this and it still is not ready. We'll return
1672 and are that this will be handled again after it is resolved. */
1673 for (i = 0; i < resolve_count; i++) {
1674 for (k = 0; k < r->res_argc; k++)
1675 silc_free(r->res_argv[k]);
1676 silc_free(r->res_argv);
1677 silc_free(r->res_argv_lens);
1678 silc_free(r->res_argv_types);
1683 /* We'll resolve this client */
1687 for (k = 0; k < resolve_count; k++) {
1688 if (resolve[k].router == entry->router) {
1695 resolve = silc_realloc(resolve, sizeof(*resolve) *
1696 (resolve_count + 1));
1697 r = &resolve[resolve_count];
1698 memset(r, 0, sizeof(*r));
1699 r->router = entry->router;
1700 r->ident = ++server->cmd_ident;
1704 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1706 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1707 sizeof(*r->res_argv_lens) *
1709 r->res_argv_types = silc_realloc(r->res_argv_types,
1710 sizeof(*r->res_argv_types) *
1712 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1713 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1714 sizeof(**r->res_argv));
1715 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1716 r->res_argv_lens[r->res_argc] = idp->len;
1717 r->res_argv_types[r->res_argc] = r->res_argc + 4;
1719 silc_buffer_free(idp);
1721 entry->resolve_cmd_ident = r->ident;
1722 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1723 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1728 /* Do the resolving */
1729 for (i = 0; i < resolve_count; i++) {
1734 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1735 now anyway so make it a good one. */
1736 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1737 r->res_argc, r->res_argv,
1741 silc_server_packet_send(server, r->router->connection,
1742 SILC_PACKET_COMMAND, cmd->packet->flags,
1743 res_cmd->data, res_cmd->len, FALSE);
1745 /* Reprocess this packet after received reply */
1746 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1748 silc_server_command_identify,
1749 silc_server_command_dup(cmd));
1750 cmd->pending = TRUE;
1752 silc_buffer_free(res_cmd);
1753 for (k = 0; k < r->res_argc; k++)
1754 silc_free(r->res_argv[k]);
1755 silc_free(r->res_argv);
1756 silc_free(r->res_argv_lens);
1757 silc_free(r->res_argv_types);
1766 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1767 SilcClientEntry *clients,
1768 SilcUInt32 clients_count,
1769 SilcServerEntry *servers,
1770 SilcUInt32 servers_count,
1771 SilcChannelEntry *channels,
1772 SilcUInt32 channels_count,
1773 ResolveError errors,
1774 SilcUInt32 errors_count,
1777 SilcServer server = cmd->server;
1778 int i, k, valid_count;
1780 SilcBuffer packet, idp;
1782 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1783 char nh[256], uh[256];
1784 SilcSocketConnection hsock;
1787 status = SILC_STATUS_OK;
1790 SilcClientEntry entry;
1791 valid_count = clients_count;
1793 if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
1794 /* Process only valid clients and ignore those that are not registered.
1795 This is checked with nickname only because when resolved client IDs
1796 we check that they are registered earlier. */
1798 for (i = 0; i < clients_count; i++) {
1799 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1806 /* No valid entries found at all, just send error */
1807 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1808 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1809 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1810 3, tmp, tmp ? strlen(tmp) : 0);
1815 /* Process all valid client entries and send command replies */
1817 if (valid_count > 1)
1818 status = SILC_STATUS_LIST_START;
1820 for (i = 0, k = 0; i < clients_count; i++) {
1826 status = SILC_STATUS_LIST_ITEM;
1827 if (valid_count > 1 && k == valid_count - 1
1828 && !servers_count && !channels_count && !errors_count)
1829 status = SILC_STATUS_LIST_END;
1830 if (count && k - 1 == count)
1831 status = SILC_STATUS_LIST_END;
1833 /* Send IDENTIFY reply */
1835 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1836 memset(uh, 0, sizeof(uh));
1837 memset(nh, 0, sizeof(nh));
1838 strncat(nh, entry->nickname, strlen(entry->nickname));
1839 if (!strchr(entry->nickname, '@')) {
1840 strncat(nh, "@", 1);
1841 if (entry->servername) {
1842 strncat(nh, entry->servername, strlen(entry->servername));
1844 len = entry->router ? strlen(entry->router->server_name) :
1845 strlen(server->server_name);
1846 strncat(nh, entry->router ? entry->router->server_name :
1847 server->server_name, len);
1851 if (!entry->username) {
1852 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1853 status, 0, ident, 2,
1854 2, idp->data, idp->len,
1857 strncat(uh, entry->username, strlen(entry->username));
1858 if (!strchr(entry->username, '@') && entry->connection) {
1859 strncat(uh, "@", 1);
1860 hsock = (SilcSocketConnection)entry->connection;
1861 len = strlen(hsock->hostname);
1862 strncat(uh, hsock->hostname, len);
1865 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1866 status, 0, ident, 3,
1867 2, idp->data, idp->len,
1872 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1873 0, packet->data, packet->len, FALSE);
1875 silc_buffer_free(packet);
1876 silc_buffer_free(idp);
1878 if (status == SILC_STATUS_LIST_END)
1885 SilcServerEntry entry;
1887 if (status == SILC_STATUS_OK && servers_count > 1)
1888 status = SILC_STATUS_LIST_START;
1890 for (i = 0, k = 0; i < servers_count; i++) {
1894 status = SILC_STATUS_LIST_ITEM;
1895 if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
1897 status = SILC_STATUS_LIST_END;
1898 if (count && k - 1 == count)
1899 status = SILC_STATUS_LIST_END;
1901 /* Send IDENTIFY reply */
1902 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1904 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1905 status, 0, ident, 2,
1906 2, idp->data, idp->len,
1907 3, entry->server_name,
1908 entry->server_name ?
1909 strlen(entry->server_name) : 0);
1910 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1911 0, packet->data, packet->len, FALSE);
1913 silc_buffer_free(packet);
1914 silc_buffer_free(idp);
1916 if (status == SILC_STATUS_LIST_END)
1923 SilcChannelEntry entry;
1925 if (status == SILC_STATUS_OK && channels_count > 1)
1926 status = SILC_STATUS_LIST_START;
1928 for (i = 0, k = 0; i < channels_count; i++) {
1929 entry = channels[i];
1932 status = SILC_STATUS_LIST_ITEM;
1933 if (channels_count > 1 && k == channels_count - 1 && !errors_count)
1934 status = SILC_STATUS_LIST_END;
1935 if (count && k - 1 == count)
1936 status = SILC_STATUS_LIST_END;
1938 /* Send IDENTIFY reply */
1939 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1941 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1942 status, 0, ident, 2,
1943 2, idp->data, idp->len,
1944 3, entry->channel_name,
1945 entry->channel_name ?
1946 strlen(entry->channel_name): 0);
1947 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1948 0, packet->data, packet->len, FALSE);
1950 silc_buffer_free(packet);
1951 silc_buffer_free(idp);
1953 if (status == SILC_STATUS_LIST_END)
1959 /* Send error replies */
1961 if (status == SILC_STATUS_OK && errors_count > 1)
1962 status = SILC_STATUS_LIST_START;
1965 for (i = 0, k = 0; i < errors_count; i++) {
1967 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
1971 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
1975 status = SILC_STATUS_LIST_ITEM;
1976 if (errors_count > 1 && k == errors_count - 1)
1977 status = SILC_STATUS_LIST_END;
1978 if (count && k - 1 == count)
1979 status = SILC_STATUS_LIST_END;
1982 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1983 (status == SILC_STATUS_OK ?
1984 errors[i].error : status),
1985 (status == SILC_STATUS_OK ?
1986 0 : errors[i].error),
1988 silc_buffer_free(idp);
1991 if (status == SILC_STATUS_LIST_END)
1999 silc_server_command_identify_process(SilcServerCommandContext cmd)
2001 SilcUInt32 count = 0;
2003 SilcClientEntry *clients = NULL;
2004 SilcServerEntry *servers = NULL;
2005 SilcChannelEntry *channels = NULL;
2006 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
2007 SilcUInt32 errors_count = 0;
2008 ResolveError errors = NULL;
2010 /* Parse the IDENTIFY request */
2011 ret = silc_server_command_identify_parse(cmd,
2012 &clients, &clients_count,
2013 &servers, &servers_count,
2014 &channels, &channels_count,
2015 &count, &errors, &errors_count);
2020 /* Check that all mandatory fields are present and request those data
2021 from the server who owns the client if necessary. */
2022 if (!silc_server_command_identify_check_client(cmd, clients,
2028 /* Send the command reply to the client */
2029 silc_server_command_identify_send_reply(cmd,
2030 clients, clients_count,
2031 servers, servers_count,
2032 channels, channels_count,
2033 errors, errors_count,
2039 silc_free(channels);
2044 SILC_SERVER_CMD_FUNC(identify)
2046 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2049 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2051 ret = silc_server_command_identify_process(cmd);
2052 silc_server_command_free(cmd);
2055 /* Server side of command NICK. Sets nickname for user. Setting
2056 nickname causes generation of a new client ID for the client. The
2057 new client ID is sent to the client after changing the nickname. */
2059 SILC_SERVER_CMD_FUNC(nick)
2061 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2062 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2063 SilcServer server = cmd->server;
2064 SilcBuffer packet, nidp, oidp = NULL;
2065 SilcClientID *new_id;
2066 SilcUInt32 nick_len;
2068 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2071 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2074 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2076 /* Check nickname */
2077 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2080 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2082 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2086 /* Check for same nickname */
2087 if (!strcmp(client->nickname, nick)) {
2088 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2092 /* Create new Client ID */
2093 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2095 cmd->server->md5hash, nick,
2099 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2100 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2103 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2106 /* Send notify about nickname change to our router. We send the new
2107 ID and ask to replace it with the old one. If we are router the
2108 packet is broadcasted. Send NICK_CHANGE notify. */
2109 if (!server->standalone)
2110 silc_server_send_notify_nick_change(server, server->router->connection,
2111 server->server_type == SILC_SERVER ?
2112 FALSE : TRUE, client->id,
2115 /* Check if anyone is watching the old nickname */
2116 if (server->server_type == SILC_ROUTER)
2117 silc_server_check_watcher_list(server, client, nick,
2118 SILC_NOTIFY_TYPE_NICK_CHANGE);
2120 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2122 /* Remove old cache entry */
2123 silc_idcache_del_by_context(server->local_list->clients, client);
2125 silc_free(client->id);
2126 client->id = new_id;
2128 silc_free(client->nickname);
2129 client->nickname = strdup(nick);
2131 /* Update client cache */
2132 silc_idcache_add(server->local_list->clients, client->nickname,
2133 client->id, (void *)client, 0, NULL);
2135 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2137 /* Send NICK_CHANGE notify to the client's channels */
2138 silc_server_send_notify_on_channels(server, NULL, client,
2139 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2140 oidp->data, oidp->len,
2141 nidp->data, nidp->len,
2143 strlen(client->nickname));
2145 /* Check if anyone is watching the new nickname */
2146 if (server->server_type == SILC_ROUTER)
2147 silc_server_check_watcher_list(server, client, NULL,
2148 SILC_NOTIFY_TYPE_NICK_CHANGE);
2151 /* Send the new Client ID as reply command back to client */
2152 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2153 SILC_STATUS_OK, 0, ident, 2,
2154 2, nidp->data, nidp->len,
2155 3, nick, strlen(nick));
2156 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2157 0, packet->data, packet->len, FALSE);
2159 silc_buffer_free(packet);
2160 silc_buffer_free(nidp);
2162 silc_buffer_free(oidp);
2165 silc_server_command_free(cmd);
2168 /* Sends the LIST command reply */
2171 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2172 SilcChannelEntry *lch,
2173 SilcUInt32 lch_count,
2174 SilcChannelEntry *gch,
2175 SilcUInt32 gch_count)
2178 SilcBuffer packet, idp;
2179 SilcChannelEntry entry;
2181 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2183 unsigned char usercount[4];
2185 int valid_lcount = 0, valid_rcount = 0;
2187 for (i = 0; i < lch_count; i++) {
2188 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2193 for (i = 0; i < gch_count; i++) {
2194 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2200 status = SILC_STATUS_OK;
2201 if ((lch_count + gch_count) > 1)
2202 status = SILC_STATUS_LIST_START;
2205 for (i = 0, k = 0; i < lch_count; i++) {
2211 status = SILC_STATUS_LIST_ITEM;
2212 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2213 status = SILC_STATUS_LIST_END;
2215 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2217 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2218 topic = "*private*";
2219 memset(usercount, 0, sizeof(usercount));
2221 topic = entry->topic;
2222 users = silc_hash_table_count(entry->user_list);
2223 SILC_PUT32_MSB(users, usercount);
2226 /* Send the reply */
2228 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2229 status, 0, ident, 4,
2230 2, idp->data, idp->len,
2231 3, entry->channel_name,
2232 strlen(entry->channel_name),
2233 4, topic, topic ? strlen(topic) : 0,
2235 silc_server_packet_send(cmd->server, cmd->sock,
2236 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2237 packet->len, FALSE);
2238 silc_buffer_free(packet);
2239 silc_buffer_free(idp);
2244 for (i = 0, k = 0; i < gch_count; i++) {
2250 status = SILC_STATUS_LIST_ITEM;
2251 if (valid_rcount > 1 && k == valid_rcount - 1)
2252 status = SILC_STATUS_LIST_END;
2254 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2256 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2257 topic = "*private*";
2258 memset(usercount, 0, sizeof(usercount));
2260 topic = entry->topic;
2261 users = entry->user_count;
2262 SILC_PUT32_MSB(users, usercount);
2265 /* Send the reply */
2267 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2268 status, 0, ident, 4,
2269 2, idp->data, idp->len,
2270 3, entry->channel_name,
2271 strlen(entry->channel_name),
2272 4, topic, topic ? strlen(topic) : 0,
2274 silc_server_packet_send(cmd->server, cmd->sock,
2275 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2276 packet->len, FALSE);
2277 silc_buffer_free(packet);
2278 silc_buffer_free(idp);
2283 /* Server side of LIST command. This lists the channel of the requested
2284 server. Secret channels are not listed. */
2286 SILC_SERVER_CMD_FUNC(list)
2288 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2289 SilcServer server = cmd->server;
2290 SilcChannelID *channel_id = NULL;
2293 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2294 SilcUInt32 lch_count = 0, gch_count = 0;
2296 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2298 /* If we are normal server, send the command to router, since we
2299 want to know all channels in the network. */
2300 if (!cmd->pending && server->server_type == SILC_SERVER &&
2301 !server->standalone) {
2303 SilcUInt16 old_ident;
2305 old_ident = silc_command_get_ident(cmd->payload);
2306 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2307 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2308 silc_server_packet_send(server, server->router->connection,
2309 SILC_PACKET_COMMAND, cmd->packet->flags,
2310 tmpbuf->data, tmpbuf->len, TRUE);
2312 /* Reprocess this packet after received reply from router */
2313 silc_server_command_pending(server, SILC_COMMAND_LIST,
2314 silc_command_get_ident(cmd->payload),
2315 silc_server_command_list,
2316 silc_server_command_dup(cmd));
2317 cmd->pending = TRUE;
2318 silc_command_set_ident(cmd->payload, old_ident);
2319 silc_buffer_free(tmpbuf);
2323 /* Get Channel ID */
2324 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2326 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2329 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2334 /* Get the channels from local list */
2335 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2338 /* Get the channels from global list */
2339 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2342 /* Send the reply */
2343 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2344 gchannels, gch_count);
2346 silc_free(lchannels);
2347 silc_free(gchannels);
2350 silc_server_command_free(cmd);
2353 /* Server side of TOPIC command. Sets topic for channel and/or returns
2354 current topic to client. */
2356 SILC_SERVER_CMD_FUNC(topic)
2358 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2359 SilcServer server = cmd->server;
2360 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2361 SilcChannelID *channel_id;
2362 SilcChannelEntry channel;
2363 SilcChannelClientEntry chl;
2364 SilcBuffer packet, idp;
2366 SilcUInt32 argc, tmp_len;
2367 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2369 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2371 argc = silc_argument_get_arg_num(cmd->args);
2373 /* Get Channel ID */
2374 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2377 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2380 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2383 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2387 /* Check whether the channel exists */
2388 channel = silc_idlist_find_channel_by_id(server->local_list,
2391 channel = silc_idlist_find_channel_by_id(server->global_list,
2394 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2395 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2403 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2406 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2411 if (strlen(tmp) > 256) {
2412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2413 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2418 /* See whether the client is on channel and has rights to change topic */
2419 if (!silc_server_client_on_channel(client, channel, &chl)) {
2420 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2421 SILC_STATUS_ERR_NOT_ON_CHANNEL,
2426 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2427 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2428 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2430 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2435 /* Set the topic for channel */
2436 silc_free(channel->topic);
2437 channel->topic = strdup(tmp);
2439 /* Send TOPIC_SET notify type to the network */
2440 if (!server->standalone)
2441 silc_server_send_notify_topic_set(server, server->router->connection,
2442 server->server_type == SILC_ROUTER ?
2443 TRUE : FALSE, channel,
2444 client->id, SILC_ID_CLIENT,
2447 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2449 /* Send notify about topic change to all clients on the channel */
2450 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2451 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2452 idp->data, idp->len,
2453 channel->topic, strlen(channel->topic));
2454 silc_buffer_free(idp);
2457 /* Send the topic to client as reply packet */
2458 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2459 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2460 SILC_STATUS_OK, 0, ident, 2,
2461 2, idp->data, idp->len,
2464 strlen(channel->topic) : 0);
2465 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2466 0, packet->data, packet->len, FALSE);
2468 silc_buffer_free(packet);
2469 silc_buffer_free(idp);
2470 silc_free(channel_id);
2473 silc_server_command_free(cmd);
2476 /* Server side of INVITE command. Invites some client to join some channel.
2477 This command is also used to manage the invite list of the channel. */
2479 SILC_SERVER_CMD_FUNC(invite)
2481 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2482 SilcServer server = cmd->server;
2483 SilcSocketConnection sock = cmd->sock, dest_sock;
2484 SilcChannelClientEntry chl;
2485 SilcClientEntry sender, dest;
2486 SilcClientID *dest_id = NULL;
2487 SilcChannelEntry channel;
2488 SilcChannelID *channel_id = NULL;
2489 SilcIDListData idata;
2490 SilcBuffer idp, idp2, packet;
2491 unsigned char *tmp, *add, *del;
2493 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2495 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2497 /* Get Channel ID */
2498 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2500 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2501 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2504 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2506 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2507 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2511 /* Get the channel entry */
2512 channel = silc_idlist_find_channel_by_id(server->local_list,
2515 channel = silc_idlist_find_channel_by_id(server->global_list,
2518 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2519 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2525 /* Check whether the sender of this command is on the channel. */
2526 sender = (SilcClientEntry)sock->user_data;
2527 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2528 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2529 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2533 /* Check whether the channel is invite-only channel. If yes then the
2534 sender of this command must be at least channel operator. */
2535 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2536 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2537 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2538 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2539 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2544 /* Get destination client ID */
2545 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2550 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2552 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2553 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2557 /* Get the client entry */
2558 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2560 if (server->server_type != SILC_SERVER || !resolve) {
2561 silc_server_command_send_status_reply(
2562 cmd, SILC_COMMAND_INVITE,
2563 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2567 /* The client info is being resolved. Reprocess this packet after
2568 receiving the reply to the query. */
2569 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2571 silc_server_command_invite,
2572 silc_server_command_dup(cmd));
2573 cmd->pending = TRUE;
2574 silc_free(channel_id);
2579 /* Check whether the requested client is already on the channel. */
2580 if (silc_server_client_on_channel(dest, channel, NULL)) {
2581 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2582 SILC_STATUS_ERR_USER_ON_CHANNEL,
2587 /* Get route to the client */
2588 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2591 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2592 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2597 memset(invite, 0, sizeof(invite));
2598 strncat(invite, dest->nickname, strlen(dest->nickname));
2599 strncat(invite, "!", 1);
2600 strncat(invite, dest->username, strlen(dest->username));
2601 if (!strchr(dest->username, '@')) {
2602 strncat(invite, "@", 1);
2603 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2606 len = strlen(invite);
2607 if (!channel->invite_list)
2608 channel->invite_list = silc_calloc(len + 2,
2609 sizeof(*channel->invite_list));
2611 channel->invite_list = silc_realloc(channel->invite_list,
2612 sizeof(*channel->invite_list) *
2614 strlen(channel->invite_list) + 2));
2615 strncat(channel->invite_list, invite, len);
2616 strncat(channel->invite_list, ",", 1);
2618 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2619 /* Send notify to the client that is invited to the channel */
2620 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2621 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2622 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2624 SILC_NOTIFY_TYPE_INVITE, 3,
2625 idp->data, idp->len,
2626 channel->channel_name,
2627 strlen(channel->channel_name),
2628 idp2->data, idp2->len);
2629 silc_buffer_free(idp);
2630 silc_buffer_free(idp2);
2634 /* Add the client to the invite list of the channel */
2635 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2637 if (!channel->invite_list)
2638 channel->invite_list = silc_calloc(len + 2,
2639 sizeof(*channel->invite_list));
2641 channel->invite_list = silc_realloc(channel->invite_list,
2642 sizeof(*channel->invite_list) *
2644 strlen(channel->invite_list) + 2));
2645 if (add[len - 1] == ',')
2646 add[len - 1] = '\0';
2648 strncat(channel->invite_list, add, len);
2649 strncat(channel->invite_list, ",", 1);
2652 /* Get the invite to be removed and remove it from the list */
2653 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2654 if (del && channel->invite_list) {
2655 char *start, *end, *n;
2657 if (!strncmp(channel->invite_list, del,
2658 strlen(channel->invite_list) - 1)) {
2659 silc_free(channel->invite_list);
2660 channel->invite_list = NULL;
2662 start = strstr(channel->invite_list, del);
2663 if (start && strlen(start) >= len) {
2665 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2666 strncat(n, channel->invite_list, start - channel->invite_list);
2667 strncat(n, end + 1, ((channel->invite_list +
2668 strlen(channel->invite_list)) - end) - 1);
2669 silc_free(channel->invite_list);
2670 channel->invite_list = n;
2675 /* Send notify to the primary router */
2676 if (!server->standalone)
2677 silc_server_send_notify_invite(server, server->router->connection,
2678 server->server_type == SILC_ROUTER ?
2679 TRUE : FALSE, channel,
2680 sender->id, add, del);
2682 /* Send command reply */
2683 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2687 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2688 SILC_STATUS_OK, 0, ident, 2,
2690 3, channel->invite_list,
2691 channel->invite_list ?
2692 strlen(channel->invite_list) : 0);
2695 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2696 SILC_STATUS_OK, 0, ident, 1,
2698 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2699 packet->data, packet->len, FALSE);
2700 silc_buffer_free(packet);
2704 silc_free(channel_id);
2705 silc_server_command_free(cmd);
2710 SilcSocketConnection sock;
2714 /* Quits connection to client. This gets called if client won't
2715 close the connection even when it has issued QUIT command. */
2717 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2719 QuitInternal q = (QuitInternal)context;
2721 /* Free all client specific data, such as client entry and entires
2722 on channels this client may be on. */
2723 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2725 q->sock->user_data = NULL;
2727 /* Close the connection on our side */
2728 silc_server_close_connection(q->server, q->sock);
2730 silc_free(q->signoff);
2734 /* Quits SILC session. This is the normal way to disconnect client. */
2736 SILC_SERVER_CMD_FUNC(quit)
2738 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2739 SilcServer server = cmd->server;
2740 SilcSocketConnection sock = cmd->sock;
2742 unsigned char *tmp = NULL;
2745 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2747 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2751 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2755 q = silc_calloc(1, sizeof(*q));
2758 q->signoff = tmp ? strdup(tmp) : NULL;
2760 /* We quit the connection with little timeout */
2761 silc_schedule_task_add(server->schedule, sock->sock,
2762 silc_server_command_quit_cb, (void *)q,
2763 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2766 silc_server_command_free(cmd);
2769 /* Server side of command KILL. This command is used by router operator
2770 to remove an client from the SILC Network temporarily. */
2772 SILC_SERVER_CMD_FUNC(kill)
2774 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2775 SilcServer server = cmd->server;
2776 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2777 SilcClientEntry remote_client;
2778 SilcClientID *client_id;
2779 unsigned char *tmp, *comment;
2780 SilcUInt32 tmp_len, tmp_len2;
2783 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2785 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2788 /* KILL command works only on router */
2789 if (server->server_type != SILC_ROUTER) {
2790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2791 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2795 /* Check whether client has the permissions. */
2796 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2797 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2798 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2802 /* Get the client ID */
2803 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2806 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2810 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2813 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2818 /* Get the client entry */
2819 remote_client = silc_idlist_find_client_by_id(server->local_list,
2820 client_id, TRUE, NULL);
2822 if (!remote_client) {
2823 remote_client = silc_idlist_find_client_by_id(server->global_list,
2824 client_id, TRUE, NULL);
2826 if (!remote_client) {
2827 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2828 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2835 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2839 /* Send reply to the sender */
2840 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2843 /* Check if anyone is watching this nickname */
2844 if (server->server_type == SILC_ROUTER)
2845 silc_server_check_watcher_list(server, client, NULL,
2846 SILC_NOTIFY_TYPE_KILLED);
2848 /* Now do the killing */
2849 silc_server_kill_client(server, remote_client, comment, client->id,
2853 silc_server_command_free(cmd);
2856 /* Server side of command INFO. This sends information about us to
2857 the client. If client requested specific server we will send the
2858 command to that server. */
2860 SILC_SERVER_CMD_FUNC(info)
2862 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2863 SilcServer server = cmd->server;
2864 SilcBuffer packet, idp;
2867 char *dest_server, *server_info = NULL, *server_name;
2868 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2869 SilcServerEntry entry = NULL;
2870 SilcServerID *server_id = NULL;
2872 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2874 /* Get server name */
2875 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2878 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2880 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2883 SILC_STATUS_ERR_NO_SERVER_ID, 0);
2889 /* Check whether we have this server cached */
2890 entry = silc_idlist_find_server_by_id(server->local_list,
2891 server_id, TRUE, NULL);
2893 entry = silc_idlist_find_server_by_id(server->global_list,
2894 server_id, TRUE, NULL);
2895 if (!entry && server->server_type != SILC_SERVER) {
2896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2897 SILC_STATUS_ERR_NO_SUCH_SERVER,
2904 /* Some buggy servers has sent request to router about themselves. */
2905 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2908 if ((!dest_server && !server_id && !entry) || (entry &&
2909 entry == server->id_entry) ||
2910 (dest_server && !cmd->pending &&
2911 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2912 /* Send our reply */
2913 char info_string[256];
2915 memset(info_string, 0, sizeof(info_string));
2916 snprintf(info_string, sizeof(info_string),
2917 "location: %s server: %s admin: %s <%s>",
2918 server->config->server_info->location,
2919 server->config->server_info->server_type,
2920 server->config->server_info->admin,
2921 server->config->server_info->email);
2923 server_info = info_string;
2924 entry = server->id_entry;
2926 /* Check whether we have this server cached */
2927 if (!entry && dest_server) {
2928 entry = silc_idlist_find_server_by_name(server->global_list,
2929 dest_server, TRUE, NULL);
2931 entry = silc_idlist_find_server_by_name(server->local_list,
2932 dest_server, TRUE, NULL);
2936 if (!cmd->pending &&
2937 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2938 /* Send to the server */
2940 SilcUInt16 old_ident;
2942 old_ident = silc_command_get_ident(cmd->payload);
2943 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2944 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2946 silc_server_packet_send(server, entry->connection,
2947 SILC_PACKET_COMMAND, cmd->packet->flags,
2948 tmpbuf->data, tmpbuf->len, TRUE);
2950 /* Reprocess this packet after received reply from router */
2951 silc_server_command_pending(server, SILC_COMMAND_INFO,
2952 silc_command_get_ident(cmd->payload),
2953 silc_server_command_info,
2954 silc_server_command_dup(cmd));
2955 cmd->pending = TRUE;
2956 silc_command_set_ident(cmd->payload, old_ident);
2957 silc_buffer_free(tmpbuf);
2961 if (!entry && !cmd->pending && !server->standalone) {
2962 /* Send to the primary router */
2964 SilcUInt16 old_ident;
2966 old_ident = silc_command_get_ident(cmd->payload);
2967 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2968 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2970 silc_server_packet_send(server, server->router->connection,
2971 SILC_PACKET_COMMAND, cmd->packet->flags,
2972 tmpbuf->data, tmpbuf->len, TRUE);
2974 /* Reprocess this packet after received reply from router */
2975 silc_server_command_pending(server, SILC_COMMAND_INFO,
2976 silc_command_get_ident(cmd->payload),
2977 silc_server_command_info,
2978 silc_server_command_dup(cmd));
2979 cmd->pending = TRUE;
2980 silc_command_set_ident(cmd->payload, old_ident);
2981 silc_buffer_free(tmpbuf);
2986 silc_free(server_id);
2989 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2990 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2994 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2996 server_info = entry->server_info;
2997 server_name = entry->server_name;
2999 /* Send the reply */
3000 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3001 SILC_STATUS_OK, 0, ident, 3,
3002 2, idp->data, idp->len,
3004 strlen(server_name),
3007 strlen(server_info) : 0);
3008 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3009 packet->data, packet->len, FALSE);
3011 silc_buffer_free(packet);
3012 silc_buffer_free(idp);
3015 silc_server_command_free(cmd);
3018 /* Server side of command PING. This just replies to the ping. */
3020 SILC_SERVER_CMD_FUNC(ping)
3022 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3023 SilcServer server = cmd->server;
3028 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3031 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3033 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3034 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3037 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3041 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3042 /* Send our reply */
3043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3046 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3047 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3054 silc_server_command_free(cmd);
3057 /* Server side of command STATS. */
3059 SILC_SERVER_CMD_FUNC(stats)
3061 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3062 SilcServer server = cmd->server;
3063 SilcServerID *server_id;
3066 SilcBuffer packet, stats;
3067 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3070 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3073 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3075 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3076 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3079 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3083 /* The ID must be ours */
3084 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3086 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3087 silc_free(server_id);
3090 silc_free(server_id);
3092 /* If we are router then just send everything we got. If we are normal
3093 server then we'll send this to our router to get all the latest
3094 statistical information. */
3095 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3096 !server->standalone) {
3097 /* Send request to our router */
3098 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3100 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3101 ++server->cmd_ident, 1,
3102 1, idp->data, idp->len);
3103 silc_server_packet_send(server, server->router->connection,
3104 SILC_PACKET_COMMAND, 0, packet->data,
3105 packet->len, FALSE);
3107 /* Reprocess this packet after received reply from router */
3108 silc_server_command_pending(server, SILC_COMMAND_STATS,
3110 silc_server_command_stats,
3111 silc_server_command_dup(cmd));
3112 cmd->pending = TRUE;
3113 silc_buffer_free(packet);
3114 silc_buffer_free(idp);
3118 /* Send our reply to sender */
3119 uptime = time(NULL) - server->starttime;
3121 stats = silc_buffer_alloc_size(60);
3122 silc_buffer_format(stats,
3123 SILC_STR_UI_INT(server->starttime),
3124 SILC_STR_UI_INT(uptime),
3125 SILC_STR_UI_INT(server->stat.my_clients),
3126 SILC_STR_UI_INT(server->stat.my_channels),
3127 SILC_STR_UI_INT(server->stat.my_server_ops),
3128 SILC_STR_UI_INT(server->stat.my_router_ops),
3129 SILC_STR_UI_INT(server->stat.cell_clients),
3130 SILC_STR_UI_INT(server->stat.cell_channels),
3131 SILC_STR_UI_INT(server->stat.cell_servers),
3132 SILC_STR_UI_INT(server->stat.clients),
3133 SILC_STR_UI_INT(server->stat.channels),
3134 SILC_STR_UI_INT(server->stat.servers),
3135 SILC_STR_UI_INT(server->stat.routers),
3136 SILC_STR_UI_INT(server->stat.server_ops),
3137 SILC_STR_UI_INT(server->stat.router_ops),
3140 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3141 SILC_STATUS_OK, 0, ident, 2,
3143 3, stats->data, stats->len);
3144 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3145 0, packet->data, packet->len, FALSE);
3146 silc_buffer_free(packet);
3147 silc_buffer_free(stats);
3150 silc_server_command_free(cmd);
3153 /* Internal routine to join channel. The channel sent to this function
3154 has been either created or resolved from ID lists. This joins the sent
3155 client to the channel. */
3157 static void silc_server_command_join_channel(SilcServer server,
3158 SilcServerCommandContext cmd,
3159 SilcChannelEntry channel,
3160 SilcClientID *client_id,
3164 const unsigned char *auth,
3165 SilcUInt32 auth_len)
3167 SilcSocketConnection sock = cmd->sock;
3169 SilcUInt32 tmp_len, user_count;
3170 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3171 SilcClientEntry client;
3172 SilcChannelClientEntry chl;
3173 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3174 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3175 char check[512], check2[512];
3176 bool founder = FALSE;
3178 unsigned char *fkey = NULL;
3179 SilcUInt32 fkey_len = 0;
3181 SILC_LOG_DEBUG(("Start"));
3186 /* Get the client entry */
3187 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3188 client = (SilcClientEntry)sock->user_data;
3190 client = silc_server_get_client_resolve(server, client_id, FALSE,
3197 silc_server_command_send_status_reply(
3198 cmd, SILC_COMMAND_JOIN,
3199 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3203 /* The client info is being resolved. Reprocess this packet after
3204 receiving the reply to the query. */
3205 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3207 silc_server_command_join,
3208 silc_server_command_dup(cmd));
3209 cmd->pending = TRUE;
3213 cmd->pending = FALSE;
3217 * Check founder auth payload if provided. If client can gain founder
3218 * privileges it can override various conditions on joining the channel,
3219 * and can have directly the founder mode set on the channel.
3221 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3222 SilcIDListData idata = (SilcIDListData)client;
3224 if (channel->founder_key && idata->public_key &&
3225 silc_pkcs_public_key_compare(channel->founder_key,
3226 idata->public_key)) {
3227 /* Check whether the client is to become founder */
3228 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3229 channel->founder_key, 0, server->sha1hash,
3230 client->id, SILC_ID_CLIENT)) {
3231 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3238 * Check channel modes
3242 memset(check, 0, sizeof(check));
3243 memset(check2, 0, sizeof(check2));
3244 strncat(check, client->nickname, strlen(client->nickname));
3245 strncat(check, "!", 1);
3246 strncat(check, client->username, strlen(client->username));
3247 if (!strchr(client->username, '@')) {
3248 strncat(check, "@", 1);
3249 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3252 strncat(check2, client->nickname, strlen(client->nickname));
3253 if (!strchr(client->nickname, '@')) {
3254 strncat(check2, "@", 1);
3255 strncat(check2, server->server_name, strlen(server->server_name));
3257 strncat(check2, "!", 1);
3258 strncat(check2, client->username, strlen(client->username));
3259 if (!strchr(client->username, '@')) {
3260 strncat(check2, "@", 1);
3261 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3264 /* Check invite list if channel is invite-only channel */
3265 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3266 if (!channel->invite_list ||
3267 (!silc_string_match(channel->invite_list, check) &&
3268 !silc_string_match(channel->invite_list, check2))) {
3269 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3270 SILC_STATUS_ERR_NOT_INVITED, 0);
3275 /* Check ban list if it exists. If the client's nickname, server,
3276 username and/or hostname is in the ban list the access to the
3277 channel is denied. */
3278 if (channel->ban_list) {
3279 if (silc_string_match(channel->ban_list, check) ||
3280 silc_string_match(channel->ban_list, check2)) {
3281 silc_server_command_send_status_reply(
3282 cmd, SILC_COMMAND_JOIN,
3283 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3288 /* Check user count limit if set. */
3289 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3290 if (silc_hash_table_count(channel->user_list) + 1 >
3291 channel->user_limit) {
3292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3293 SILC_STATUS_ERR_CHANNEL_IS_FULL,
3300 /* Check the channel passphrase if set. */
3301 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3302 /* Get passphrase */
3303 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3305 passphrase = silc_memdup(tmp, tmp_len);
3307 if (!passphrase || !channel->passphrase ||
3308 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3310 SILC_STATUS_ERR_BAD_PASSWORD, 0);
3316 * Client is allowed to join to the channel. Make it happen.
3319 /* Check whether the client already is on the channel */
3320 if (silc_server_client_on_channel(client, channel, NULL)) {
3321 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3322 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3326 /* Generate new channel key as protocol dictates */
3328 if (!silc_server_create_channel_key(server, channel, 0))
3331 /* Send the channel key. This is broadcasted to the channel but is not
3332 sent to the client who is joining to the channel. */
3333 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3334 silc_server_send_channel_key(server, NULL, channel,
3335 server->server_type == SILC_ROUTER ?
3336 FALSE : !server->standalone);
3339 /* Join the client to the channel by adding it to channel's user list.
3340 Add also the channel to client entry's channels list for fast cross-
3342 chl = silc_calloc(1, sizeof(*chl));
3344 chl->client = client;
3345 chl->channel = channel;
3346 silc_hash_table_add(channel->user_list, client, chl);
3347 silc_hash_table_add(client->channels, channel, chl);
3348 channel->user_count++;
3349 channel->disabled = FALSE;
3351 /* Get users on the channel */
3352 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3355 /* Encode Client ID Payload of the original client who wants to join */
3356 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3358 /* Encode command reply packet */
3359 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3360 SILC_PUT32_MSB(channel->mode, mode);
3361 SILC_PUT32_MSB(created, tmp2);
3362 SILC_PUT32_MSB(user_count, tmp3);
3364 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3365 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3366 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3369 strlen(channel->channel_key->
3371 channel->channel_key->cipher->name,
3372 channel->key_len / 8, channel->key);
3376 if (channel->founder_key)
3377 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3380 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3381 SILC_STATUS_OK, 0, ident, 14,
3382 2, channel->channel_name,
3383 strlen(channel->channel_name),
3384 3, chidp->data, chidp->len,
3385 4, clidp->data, clidp->len,
3388 7, keyp ? keyp->data : NULL,
3389 keyp ? keyp->len : 0,
3390 8, channel->ban_list,
3392 strlen(channel->ban_list) : 0,
3393 9, channel->invite_list,
3394 channel->invite_list ?
3395 strlen(channel->invite_list) : 0,
3398 strlen(channel->topic) : 0,
3399 11, silc_hmac_get_name(channel->hmac),
3400 strlen(silc_hmac_get_name(channel->
3403 13, user_list->data, user_list->len,
3404 14, mode_list->data,
3406 15, fkey, fkey_len);
3408 /* Send command reply */
3409 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3410 reply->data, reply->len, FALSE);
3412 /* Send JOIN notify to locally connected clients on the channel. If
3413 we are normal server then router will send or have sent JOIN notify
3414 already. However since we've added the client already to our channel
3415 we'll ignore it (in packet_receive.c) so we must send it here. If
3416 we are router then this will send it to local clients and local
3418 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3419 SILC_NOTIFY_TYPE_JOIN, 2,
3420 clidp->data, clidp->len,
3421 chidp->data, chidp->len);
3423 /* Update statistics */
3424 server->stat.my_chanclients++;
3425 if (server->server_type == SILC_ROUTER) {
3426 server->stat.cell_chanclients++;
3427 server->stat.chanclients++;
3430 if (!cmd->pending) {
3431 /* Send JOIN notify packet to our primary router */
3432 if (!server->standalone)
3433 silc_server_send_notify_join(server, server->router->connection,
3434 server->server_type == SILC_ROUTER ?
3435 TRUE : FALSE, channel, client->id);
3438 /* Distribute the channel key to all backup routers. */
3439 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3440 keyp->data, keyp->len, FALSE, TRUE);
3442 /* If client became founder by providing correct founder auth data
3443 notify the mode change to the channel. */
3445 SILC_PUT32_MSB(chl->mode, mode);
3446 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3447 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3448 clidp->data, clidp->len,
3449 mode, 4, clidp->data, clidp->len,
3452 /* Set CUMODE notify type to network */
3453 if (!server->standalone)
3454 silc_server_send_notify_cumode(server, server->router->connection,
3455 server->server_type == SILC_ROUTER ?
3456 TRUE : FALSE, channel,
3457 chl->mode, client->id, SILC_ID_CLIENT,
3458 client->id, channel->founder_key);
3462 silc_buffer_free(reply);
3463 silc_buffer_free(clidp);
3464 silc_buffer_free(chidp);
3465 silc_buffer_free(keyp);
3466 silc_buffer_free(user_list);
3467 silc_buffer_free(mode_list);
3471 silc_free(passphrase);
3474 /* Server side of command JOIN. Joins client into requested channel. If
3475 the channel does not exist it will be created. */
3477 SILC_SERVER_CMD_FUNC(join)
3479 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3480 SilcServer server = cmd->server;
3481 unsigned char *auth;
3482 SilcUInt32 tmp_len, auth_len;
3483 char *tmp, *channel_name = NULL, *cipher, *hmac;
3484 SilcChannelEntry channel;
3485 SilcUInt32 umode = 0;
3486 bool created = FALSE, create_key = TRUE;
3487 SilcClientID *client_id;
3489 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3491 /* Get channel name */
3492 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3494 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3495 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3502 channel_name[255] = '\0';
3504 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3506 SILC_STATUS_ERR_BAD_CHANNEL, 0);
3510 /* Get Client ID of the client who is joining to the channel */
3511 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3513 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3514 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3518 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3521 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3526 /* Get cipher, hmac name and auth payload */
3527 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3528 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3529 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3531 /* See if the channel exists */
3532 channel = silc_idlist_find_channel_by_name(server->local_list,
3533 channel_name, NULL);
3535 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3536 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3537 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3540 (channel->disabled && server->server_type != SILC_ROUTER)) {
3541 /* Channel not found */
3543 /* If we are standalone server we don't have a router, we just create
3544 the channel by ourselves. */
3545 if (server->standalone) {
3546 channel = silc_server_create_new_channel(server, server->id, cipher,
3547 hmac, channel_name, TRUE);
3549 silc_server_command_send_status_reply(
3550 cmd, SILC_COMMAND_JOIN,
3551 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3556 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3562 /* The channel does not exist on our server. If we are normal server
3563 we will send JOIN command to our router which will handle the
3564 joining procedure (either creates the channel if it doesn't exist
3565 or joins the client to it). */
3566 if (server->server_type != SILC_ROUTER) {
3568 SilcUInt16 old_ident;
3570 /* If this is pending command callback then we've resolved
3571 it and it didn't work, return since we've notified the
3572 client already in the command reply callback. */
3576 old_ident = silc_command_get_ident(cmd->payload);
3577 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3578 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3580 /* Send JOIN command to our router */
3581 silc_server_packet_send(server, (SilcSocketConnection)
3582 server->router->connection,
3583 SILC_PACKET_COMMAND, cmd->packet->flags,
3584 tmpbuf->data, tmpbuf->len, TRUE);
3586 /* Reprocess this packet after received reply from router */
3587 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3588 silc_command_get_ident(cmd->payload),
3589 silc_server_command_join,
3590 silc_server_command_dup(cmd));
3591 cmd->pending = TRUE;
3592 silc_command_set_ident(cmd->payload, old_ident);
3593 silc_buffer_free(tmpbuf);
3597 /* We are router and the channel does not seem exist so we will check
3598 our global list as well for the channel. */
3599 channel = silc_idlist_find_channel_by_name(server->global_list,
3600 channel_name, NULL);
3602 /* Channel really does not exist, create it */
3603 channel = silc_server_create_new_channel(server, server->id, cipher,
3604 hmac, channel_name, TRUE);
3606 silc_server_command_send_status_reply(
3607 cmd, SILC_COMMAND_JOIN,
3608 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3612 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3620 /* Channel not found */
3622 /* If the command came from router and we are normal server then
3623 something went wrong with the joining as the channel was not found.
3624 We can't do anything else but ignore this. */
3625 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3626 server->server_type != SILC_ROUTER)
3629 /* We are router and the channel does not seem exist so we will check
3630 our global list as well for the channel. */
3631 channel = silc_idlist_find_channel_by_name(server->global_list,
3632 channel_name, NULL);
3634 /* Channel really does not exist, create it */
3635 channel = silc_server_create_new_channel(server, server->id, cipher,
3636 hmac, channel_name, TRUE);
3638 silc_server_command_send_status_reply(
3639 cmd, SILC_COMMAND_JOIN,
3640 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3644 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3651 /* Check whether the channel was created by our router */
3652 if (cmd->pending && context2) {
3653 SilcServerCommandReplyContext reply = context2;
3655 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3656 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3657 SILC_GET32_MSB(created, tmp);
3658 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3659 create_key = FALSE; /* Router returned the key already */
3662 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3663 !channel->disabled && !silc_hash_table_count(channel->user_list))
3667 /* If the channel does not have global users and is also empty the client
3668 will be the channel founder and operator. */
3669 if (!channel->disabled &&
3670 !channel->global_users && !silc_hash_table_count(channel->user_list))
3671 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3673 /* Join to the channel */
3674 silc_server_command_join_channel(server, cmd, channel, client_id,
3675 created, create_key, umode,
3678 silc_free(client_id);
3681 silc_server_command_free(cmd);
3684 /* Server side of command MOTD. Sends server's current "message of the
3685 day" to the client. */
3687 SILC_SERVER_CMD_FUNC(motd)
3689 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3690 SilcServer server = cmd->server;
3691 SilcBuffer packet, idp;
3692 char *motd, *dest_server;
3693 SilcUInt32 motd_len;
3694 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3696 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3698 /* Get server name */
3699 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3701 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3702 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3706 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3709 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3711 if (server->config && server->config->server_info &&
3712 server->config->server_info->motd_file) {
3714 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3719 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3726 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3732 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3733 packet->data, packet->len, FALSE);
3734 silc_buffer_free(packet);
3735 silc_buffer_free(idp);
3737 SilcServerEntry entry;
3739 /* Check whether we have this server cached */
3740 entry = silc_idlist_find_server_by_name(server->global_list,
3741 dest_server, TRUE, NULL);
3743 entry = silc_idlist_find_server_by_name(server->local_list,
3744 dest_server, TRUE, NULL);
3747 if (server->server_type != SILC_SERVER && !cmd->pending &&
3748 entry && !entry->motd) {
3749 /* Send to the server */
3751 SilcUInt16 old_ident;
3753 old_ident = silc_command_get_ident(cmd->payload);
3754 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3755 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3757 silc_server_packet_send(server, entry->connection,
3758 SILC_PACKET_COMMAND, cmd->packet->flags,
3759 tmpbuf->data, tmpbuf->len, TRUE);
3761 /* Reprocess this packet after received reply from router */
3762 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3763 silc_command_get_ident(cmd->payload),
3764 silc_server_command_motd,
3765 silc_server_command_dup(cmd));
3766 cmd->pending = TRUE;
3767 silc_command_set_ident(cmd->payload, old_ident);
3768 silc_buffer_free(tmpbuf);
3772 if (!entry && !cmd->pending && !server->standalone) {
3773 /* Send to the primary router */
3775 SilcUInt16 old_ident;
3777 old_ident = silc_command_get_ident(cmd->payload);
3778 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3779 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3781 silc_server_packet_send(server, server->router->connection,
3782 SILC_PACKET_COMMAND, cmd->packet->flags,
3783 tmpbuf->data, tmpbuf->len, TRUE);
3785 /* Reprocess this packet after received reply from router */
3786 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3787 silc_command_get_ident(cmd->payload),
3788 silc_server_command_motd,
3789 silc_server_command_dup(cmd));
3790 cmd->pending = TRUE;
3791 silc_command_set_ident(cmd->payload, old_ident);
3792 silc_buffer_free(tmpbuf);
3797 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3798 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3802 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3803 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3804 SILC_STATUS_OK, 0, ident, 2,
3808 strlen(entry->motd) : 0);
3809 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3810 packet->data, packet->len, FALSE);
3811 silc_buffer_free(packet);
3812 silc_buffer_free(idp);
3816 silc_server_command_free(cmd);
3819 /* Server side of command UMODE. Client can use this command to set/unset
3820 user mode. Client actually cannot set itself to be as server/router
3821 operator so this can be used only to unset the modes. */
3823 SILC_SERVER_CMD_FUNC(umode)
3825 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3826 SilcServer server = cmd->server;
3827 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3829 unsigned char *tmp_mask, m[4];
3830 SilcUInt32 mask = 0;
3831 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3832 bool set_mask = FALSE;
3834 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3837 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3839 /* Get the client's mode mask */
3840 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3842 SILC_GET32_MSB(mask, tmp_mask);
3847 /* Check that mode changing is allowed. */
3848 if (!silc_server_check_umode_rights(server, client, mask)) {
3849 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3850 SILC_STATUS_ERR_PERM_DENIED, 0);
3854 /* Anonymous mode cannot be set by client */
3855 if (mask & SILC_UMODE_ANONYMOUS) {
3856 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3857 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3858 SILC_STATUS_ERR_PERM_DENIED, 0);
3862 if (client->mode & SILC_UMODE_ANONYMOUS) {
3863 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3864 SILC_STATUS_ERR_PERM_DENIED, 0);
3869 /* Update statistics */
3870 if (mask & SILC_UMODE_GONE) {
3871 if (!(client->mode & SILC_UMODE_GONE))
3872 server->stat.my_aways++;
3874 if (client->mode & SILC_UMODE_GONE)
3875 server->stat.my_aways--;
3878 /* Change the mode */
3879 client->mode = mask;
3881 /* Send UMODE change to primary router */
3882 if (!server->standalone)
3883 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3884 client->id, client->mode);
3886 /* Check if anyone is watching this nickname */
3887 if (server->server_type == SILC_ROUTER)
3888 silc_server_check_watcher_list(server, client, NULL,
3889 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3892 /* Send command reply to sender */
3893 SILC_PUT32_MSB(client->mode, m);
3894 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3895 SILC_STATUS_OK, 0, ident, 1,
3897 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3898 packet->data, packet->len, FALSE);
3899 silc_buffer_free(packet);
3902 silc_server_command_free(cmd);
3905 /* Server side command of CMODE. Changes channel mode */
3907 SILC_SERVER_CMD_FUNC(cmode)
3909 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3910 SilcServer server = cmd->server;
3911 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3912 SilcIDListData idata = (SilcIDListData)client;
3913 SilcChannelID *channel_id = NULL;
3914 SilcChannelEntry channel;
3915 SilcChannelClientEntry chl;
3916 SilcBuffer packet, cidp;
3917 unsigned char *tmp, *tmp_id, *tmp_mask;
3918 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3919 SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3920 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3921 bool set_mask = FALSE;
3922 SilcPublicKey founder_key = NULL;
3923 unsigned char *fkey = NULL;
3924 SilcUInt32 fkey_len = 0;
3926 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3928 /* Get Channel ID */
3929 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3931 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3932 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3935 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3937 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3938 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3942 /* Get the channel mode mask */
3943 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3945 SILC_GET32_MSB(mode_mask, tmp_mask);
3949 /* Get channel entry */
3950 channel = silc_idlist_find_channel_by_id(server->local_list,
3953 channel = silc_idlist_find_channel_by_id(server->global_list,
3956 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3957 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3963 /* Check whether this client is on the channel */
3964 if (!silc_server_client_on_channel(client, channel, &chl)) {
3965 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3966 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3970 /* Check that client has rights to change any requested channel modes */
3971 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
3973 silc_server_command_send_status_reply(
3974 cmd, SILC_COMMAND_CMODE,
3975 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
3976 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3977 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
3981 /* If mode mask was not sent as argument then merely return the current
3982 mode mask to the sender. */
3985 SILC_PUT32_MSB(channel->mode, m);
3986 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3987 SILC_STATUS_OK, 0, ident, 2,
3988 2, tmp_id, tmp_len2,
3990 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3991 packet->data, packet->len, FALSE);
3992 silc_buffer_free(packet);
3997 * Check the modes. Modes that requires nothing special operation are
4001 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4002 /* Channel uses private keys to protect traffic. Client(s) has set the
4003 key locally they want to use, server does not know that key. */
4004 /* Nothing interesting to do here */
4006 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4007 /* The mode is removed and we need to generate and distribute
4008 new channel key. Clients are not using private channel keys
4009 anymore after this. */
4011 /* Re-generate channel key */
4012 if (!silc_server_create_channel_key(server, channel, 0))
4015 /* Send the channel key. This sends it to our local clients and if
4016 we are normal server to our router as well. */
4017 silc_server_send_channel_key(server, NULL, channel,
4018 server->server_type == SILC_ROUTER ?
4019 FALSE : !server->standalone);
4021 cipher = channel->channel_key->cipher->name;
4022 hmac = (char *)silc_hmac_get_name(channel->hmac);
4026 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4027 /* User limit is set on channel */
4028 SilcUInt32 user_limit;
4030 /* Get user limit */
4031 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4033 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4035 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4039 SILC_GET32_MSB(user_limit, tmp);
4040 channel->user_limit = user_limit;
4043 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4044 /* User limit mode is unset. Remove user limit */
4045 channel->user_limit = 0;
4048 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4049 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4050 /* Passphrase has been set to channel */
4052 /* Get the passphrase */
4053 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4055 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4056 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4060 /* Save the passphrase */
4061 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4064 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4065 /* Passphrase mode is unset. remove the passphrase */
4066 silc_free(channel->passphrase);
4067 channel->passphrase = NULL;
4071 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4072 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4073 /* Cipher to use protect the traffic */
4074 SilcCipher newkey, oldkey;
4077 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4079 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4080 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4084 /* Delete old cipher and allocate the new one */
4085 if (!silc_cipher_alloc(cipher, &newkey)) {
4086 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4087 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4091 oldkey = channel->channel_key;
4092 channel->channel_key = newkey;
4094 /* Re-generate channel key */
4095 if (!silc_server_create_channel_key(server, channel, 0)) {
4096 /* We don't have new key, revert to old one */
4097 channel->channel_key = oldkey;
4101 /* Remove old channel key for good */
4102 silc_cipher_free(oldkey);
4104 /* Send the channel key. This sends it to our local clients and if
4105 we are normal server to our router as well. */
4106 silc_server_send_channel_key(server, NULL, channel,
4107 server->server_type == SILC_ROUTER ?
4108 FALSE : !server->standalone);
4111 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4112 /* Cipher mode is unset. Remove the cipher and revert back to
4114 SilcCipher newkey, oldkey;
4115 cipher = channel->cipher;
4117 /* Delete old cipher and allocate default one */
4118 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4119 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4120 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4124 oldkey = channel->channel_key;
4125 channel->channel_key = newkey;
4127 /* Re-generate channel key */
4128 if (!silc_server_create_channel_key(server, channel, 0)) {
4129 /* We don't have new key, revert to old one */
4130 channel->channel_key = oldkey;
4134 /* Remove old channel key for good */
4135 silc_cipher_free(oldkey);
4137 /* Send the channel key. This sends it to our local clients and if
4138 we are normal server to our router as well. */
4139 silc_server_send_channel_key(server, NULL, channel,
4140 server->server_type == SILC_ROUTER ?
4141 FALSE : !server->standalone);
4145 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4146 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4147 /* HMAC to use protect the traffic */
4148 unsigned char hash[32];
4152 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4154 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4155 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4159 /* Delete old hmac and allocate the new one */
4160 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4161 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4162 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4166 silc_hmac_free(channel->hmac);
4167 channel->hmac = newhmac;
4169 /* Set the HMAC key out of current channel key. The client must do
4171 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4172 channel->key_len / 8, hash);
4173 silc_hmac_set_key(channel->hmac, hash,
4174 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4175 memset(hash, 0, sizeof(hash));
4178 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4179 /* Hmac mode is unset. Remove the hmac and revert back to
4182 unsigned char hash[32];
4183 hmac = channel->hmac_name;
4185 /* Delete old hmac and allocate default one */
4186 silc_hmac_free(channel->hmac);
4187 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4188 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4189 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4193 silc_hmac_free(channel->hmac);
4194 channel->hmac = newhmac;
4196 /* Set the HMAC key out of current channel key. The client must do
4198 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4199 channel->key_len / 8,
4201 silc_hmac_set_key(channel->hmac, hash,
4202 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4203 memset(hash, 0, sizeof(hash));
4207 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4208 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4209 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4210 /* Set the founder authentication */
4211 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4213 silc_server_command_send_status_reply(
4214 cmd, SILC_COMMAND_CMODE,
4215 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4219 /* Verify the payload before setting the mode */
4220 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4221 idata->public_key, 0, server->sha1hash,
4222 client->id, SILC_ID_CLIENT)) {
4223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4224 SILC_STATUS_ERR_AUTH_FAILED,
4229 /* Save the public key */
4230 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4231 if (!channel->founder_key) {
4232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4233 SILC_STATUS_ERR_AUTH_FAILED,
4238 founder_key = channel->founder_key;
4239 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4241 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4242 SILC_STATUS_ERR_AUTH_FAILED,
4249 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4250 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4251 if (channel->founder_key)
4252 silc_pkcs_public_key_free(channel->founder_key);
4253 channel->founder_key = NULL;
4258 /* Finally, set the mode */
4259 channel->mode = mode_mask;
4261 /* Send CMODE_CHANGE notify. */
4262 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4263 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4264 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4265 cidp->data, cidp->len,
4267 cipher, cipher ? strlen(cipher) : 0,
4268 hmac, hmac ? strlen(hmac) : 0,
4269 passphrase, passphrase ?
4270 strlen(passphrase) : 0,
4273 /* Set CMODE notify type to network */
4274 if (!server->standalone)
4275 silc_server_send_notify_cmode(server, server->router->connection,
4276 server->server_type == SILC_ROUTER ?
4277 TRUE : FALSE, channel,
4278 mode_mask, client->id, SILC_ID_CLIENT,
4279 cipher, hmac, passphrase, founder_key);
4281 /* Send command reply to sender */
4282 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4283 SILC_STATUS_OK, 0, ident, 2,
4284 2, tmp_id, tmp_len2,
4286 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4287 packet->data, packet->len, FALSE);
4289 silc_buffer_free(packet);
4290 silc_buffer_free(cidp);
4294 silc_free(channel_id);
4295 silc_server_command_free(cmd);
4298 /* Server side of CUMODE command. Changes client's mode on a channel. */
4300 SILC_SERVER_CMD_FUNC(cumode)
4302 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4303 SilcServer server = cmd->server;
4304 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4305 SilcIDListData idata = (SilcIDListData)client;
4306 SilcChannelID *channel_id;
4307 SilcClientID *client_id;
4308 SilcChannelEntry channel;
4309 SilcClientEntry target_client;
4310 SilcChannelClientEntry chl;
4311 SilcBuffer packet, idp;
4312 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4313 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4315 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4316 SilcPublicKey founder_key = NULL;
4317 unsigned char *fkey = NULL;
4318 SilcUInt32 fkey_len = 0;
4320 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4322 /* Get Channel ID */
4323 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4326 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4329 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4332 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4336 /* Get channel entry */
4337 channel = silc_idlist_find_channel_by_id(server->local_list,
4340 channel = silc_idlist_find_channel_by_id(server->global_list,
4343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4344 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4350 /* Check whether sender is on the channel */
4351 if (!silc_server_client_on_channel(client, channel, &chl)) {
4352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4353 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4356 sender_mask = chl->mode;
4358 /* Get the target client's channel mode mask */
4359 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4361 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4362 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4366 SILC_GET32_MSB(target_mask, tmp_mask);
4368 /* Get target Client ID */
4369 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4371 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4372 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4375 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4377 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4378 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4382 /* Get target client's entry */
4383 target_client = silc_idlist_find_client_by_id(server->local_list,
4384 client_id, TRUE, NULL);
4385 if (!target_client) {
4386 target_client = silc_idlist_find_client_by_id(server->global_list,
4387 client_id, TRUE, NULL);
4390 if (target_client != client &&
4391 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4392 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4393 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4394 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4398 /* Check whether target client is on the channel */
4399 if (target_client != client) {
4400 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4401 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4402 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4411 /* If the target client is founder, no one else can change their mode
4413 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4414 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4415 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4420 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4421 if (target_client != client) {
4422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4423 SILC_STATUS_ERR_NOT_YOU, 0);
4427 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4428 /* The client tries to claim the founder rights. */
4429 unsigned char *tmp_auth;
4430 SilcUInt32 tmp_auth_len;
4431 SilcChannelClientEntry chl2;
4432 SilcHashTableList htl;
4434 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4435 !channel->founder_key || !idata->public_key ||
4436 !silc_pkcs_public_key_compare(channel->founder_key,
4437 idata->public_key)) {
4438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4439 SILC_STATUS_ERR_AUTH_FAILED, 0);
4443 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4445 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4446 SILC_STATUS_ERR_AUTH_FAILED, 0);
4450 /* Verify the authentication payload */
4451 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4452 channel->founder_key, 0, server->sha1hash,
4453 client->id, SILC_ID_CLIENT)) {
4454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4455 SILC_STATUS_ERR_AUTH_FAILED, 0);
4460 founder_key = channel->founder_key;
4461 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4464 SILC_STATUS_ERR_AUTH_FAILED, 0);
4468 /* There cannot be anyone else as founder on the channel now. This
4469 client is definitely the founder due to this authentication */
4470 silc_hash_table_list(channel->user_list, &htl);
4471 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4472 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4473 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4474 silc_server_force_cumode_change(server, NULL, channel, chl2,
4478 silc_hash_table_list_reset(&htl);
4480 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4483 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4484 if (target_client == client) {
4485 /* Remove channel founder rights from itself */
4486 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4489 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4490 SILC_STATUS_ERR_NOT_YOU, 0);
4496 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4497 /* Promote to operator */
4498 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4499 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4500 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4502 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4507 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4511 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4512 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4513 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4515 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4520 /* Demote to normal user */
4521 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4526 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4527 if (target_client != client) {
4528 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4529 SILC_STATUS_ERR_NOT_YOU, 0);
4533 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4534 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4538 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4539 if (target_client != client) {
4540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4541 SILC_STATUS_ERR_NOT_YOU, 0);
4545 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4550 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4551 if (target_client != client) {
4552 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4553 SILC_STATUS_ERR_NOT_YOU, 0);
4557 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4558 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4562 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4563 if (target_client != client) {
4564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4565 SILC_STATUS_ERR_NOT_YOU, 0);
4569 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4574 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4575 if (target_client != client) {
4576 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4577 SILC_STATUS_ERR_NOT_YOU, 0);
4581 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4582 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4586 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4587 if (target_client != client) {
4588 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4589 SILC_STATUS_ERR_NOT_YOU, 0);
4593 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4598 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4599 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4600 if (client == target_client) {
4601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4602 SILC_STATUS_ERR_PERM_DENIED, 0);
4605 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4609 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4610 if (client == target_client) {
4611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4612 SILC_STATUS_ERR_PERM_DENIED, 0);
4615 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4620 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4621 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4623 /* Send notify to channel, notify only if mode was actually changed. */
4625 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4626 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4627 idp->data, idp->len,
4632 /* Set CUMODE notify type to network */
4633 if (!server->standalone)
4634 silc_server_send_notify_cumode(server, server->router->connection,
4635 server->server_type == SILC_ROUTER ?
4636 TRUE : FALSE, channel,
4637 target_mask, client->id,
4639 target_client->id, founder_key);
4642 /* Send command reply to sender */
4643 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4644 SILC_STATUS_OK, 0, ident, 3,
4646 3, tmp_ch_id, tmp_ch_len,
4647 4, tmp_id, tmp_len);
4648 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4649 packet->data, packet->len, FALSE);
4651 silc_buffer_free(packet);
4652 silc_free(channel_id);
4653 silc_free(client_id);
4654 silc_buffer_free(idp);
4658 silc_server_command_free(cmd);
4661 /* Server side of KICK command. Kicks client out of channel. */
4663 SILC_SERVER_CMD_FUNC(kick)
4665 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4666 SilcServer server = cmd->server;
4667 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4668 SilcClientEntry target_client;
4669 SilcChannelID *channel_id;
4670 SilcClientID *client_id;
4671 SilcChannelEntry channel;
4672 SilcChannelClientEntry chl;
4674 SilcUInt32 tmp_len, target_idp_len;
4675 unsigned char *tmp, *comment, *target_idp;
4677 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4679 /* Get Channel ID */
4680 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4683 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4686 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4688 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4689 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4693 /* Get channel entry */
4694 channel = silc_idlist_find_channel_by_id(server->local_list,
4697 channel = silc_idlist_find_channel_by_id(server->local_list,
4700 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4701 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4707 /* Check whether sender is on the channel */
4708 if (!silc_server_client_on_channel(client, channel, &chl)) {
4709 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4710 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4714 /* Check that the kicker is channel operator or channel founder */
4715 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4716 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4717 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4718 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4722 /* Get target Client ID */
4723 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4725 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4726 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4729 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4731 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4732 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4736 /* Get target client's entry */
4737 target_client = silc_idlist_find_client_by_id(server->local_list,
4738 client_id, TRUE, NULL);
4739 if (!target_client) {
4740 target_client = silc_idlist_find_client_by_id(server->global_list,
4741 client_id, TRUE, NULL);
4744 /* Check whether target client is on the channel */
4745 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4746 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4747 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4752 /* Check that the target client is not channel founder. Channel founder
4753 cannot be kicked from the channel. */
4754 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4755 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4756 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4763 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4767 /* Send command reply to sender */
4768 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4771 /* Send KICKED notify to local clients on the channel */
4772 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4773 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4774 SILC_NOTIFY_TYPE_KICKED, 3,
4775 target_idp, target_idp_len,
4776 comment, comment ? strlen(comment) : 0,
4777 idp->data, idp->len);
4778 silc_buffer_free(idp);
4780 /* Remove the client from the channel. If the channel does not exist
4781 after removing the client then the client kicked itself off the channel
4782 and we don't have to send anything after that. */
4783 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4784 target_client, FALSE))
4787 /* Send KICKED notify to primary route */
4788 if (!server->standalone)
4789 silc_server_send_notify_kicked(server, server->router->connection,
4790 server->server_type == SILC_ROUTER ?
4791 TRUE : FALSE, channel,
4792 target_client->id, client->id, comment);
4794 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4795 /* Re-generate channel key */
4796 if (!silc_server_create_channel_key(server, channel, 0))
4799 /* Send the channel key to the channel. The key of course is not sent
4800 to the client who was kicked off the channel. */
4801 silc_server_send_channel_key(server, target_client->connection, channel,
4802 server->server_type == SILC_ROUTER ?
4803 FALSE : !server->standalone);
4807 silc_server_command_free(cmd);
4810 /* Server side of OPER command. Client uses this comand to obtain server
4811 operator privileges to this server/router. */
4813 SILC_SERVER_CMD_FUNC(oper)
4815 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4816 SilcServer server = cmd->server;
4817 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4818 unsigned char *username, *auth;
4820 SilcServerConfigAdmin *admin;
4821 SilcIDListData idata = (SilcIDListData)client;
4822 bool result = FALSE;
4823 SilcPublicKey cached_key;
4825 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4827 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4830 /* Get the username */
4831 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4834 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4839 /* Get the admin configuration */
4840 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4841 username, client->nickname);
4843 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4844 username, client->nickname);
4846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4847 SILC_STATUS_ERR_AUTH_FAILED,
4853 /* Get the authentication payload */
4854 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4856 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4857 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4862 /* Verify the authentication data. If both passphrase and public key
4863 is set then try both of them. */
4864 if (admin->passphrase)
4865 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4866 admin->passphrase, admin->passphrase_len,
4867 idata->hash, client->id, SILC_ID_CLIENT);
4868 if (!result && admin->publickeys) {
4869 cached_key = silc_server_get_public_key(server, admin->publickeys);
4872 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4873 cached_key, 0, idata->hash,
4874 client->id, SILC_ID_CLIENT);
4877 /* Authentication failed */
4878 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4879 SILC_STATUS_ERR_AUTH_FAILED,
4884 /* Client is now server operator */
4885 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4887 /* Update statistics */
4888 if (client->connection)
4889 server->stat.my_server_ops++;
4890 if (server->server_type == SILC_ROUTER)
4891 server->stat.server_ops++;
4893 /* Send UMODE change to primary router */
4894 if (!server->standalone)
4895 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4896 client->id, client->mode);
4898 /* Check if anyone is watching this nickname */
4899 if (server->server_type == SILC_ROUTER)
4900 silc_server_check_watcher_list(server, client, NULL,
4901 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4903 /* Send reply to the sender */
4904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4908 silc_server_command_free(cmd);
4911 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4913 QuitInternal q = (QuitInternal)context;
4914 SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4916 /* If there is pending outgoing data for the client then purge it
4917 to the network before closing connection. */
4918 silc_server_packet_queue_purge(q->server, q->sock);
4920 /* Close the connection on our side */
4921 client->router = NULL;
4922 client->connection = NULL;
4923 q->sock->user_data = NULL;
4924 silc_server_close_connection(q->server, q->sock);
4929 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4931 QuitInternal q = (QuitInternal)context;
4932 SilcClientID *client_id = (SilcClientID *)q->sock;
4933 SilcClientEntry client;
4935 SILC_LOG_DEBUG(("Start"));
4937 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4940 if (client && client->mode & SILC_UMODE_DETACHED)
4941 silc_server_free_client_data(q->server, NULL, client, TRUE,
4944 silc_free(client_id);
4948 /* Server side of DETACH command. Detached the client from the network
4949 by closing the connection but preserving the session. */
4951 SILC_SERVER_CMD_FUNC(detach)
4953 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4954 SilcServer server = cmd->server;
4955 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4958 if (server->config->detach_disabled) {
4959 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4960 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
4964 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4967 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4969 /* Send the user mode notify to notify that client is detached */
4970 client->mode |= SILC_UMODE_DETACHED;
4971 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4972 client->last_command = 0;
4973 client->fast_command = 0;
4974 if (!server->standalone)
4975 silc_server_send_notify_umode(server, server->router->connection,
4976 server->server_type == SILC_SERVER ?
4977 FALSE : TRUE, client->id, client->mode);
4978 server->stat.my_detached++;
4980 /* Check if anyone is watching this nickname */
4981 if (server->server_type == SILC_ROUTER)
4982 silc_server_check_watcher_list(server, client, NULL,
4983 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4985 q = silc_calloc(1, sizeof(*q));
4987 q->sock = cmd->sock;
4988 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4989 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4991 if (server->config->detach_timeout) {
4992 q = silc_calloc(1, sizeof(*q));
4994 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4995 silc_schedule_task_add(server->schedule, 0,
4996 silc_server_command_detach_timeout,
4997 q, server->config->detach_timeout * 60,
4998 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5001 /* Send reply to the sender */
5002 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5006 silc_server_command_free(cmd);
5009 /* Server side of WATCH command. */
5011 SILC_SERVER_CMD_FUNC(watch)
5013 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5014 SilcServer server = cmd->server;
5015 char *add_nick, *del_nick;
5016 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5018 unsigned char hash[16], *tmp;
5019 SilcClientEntry client;
5020 SilcClientID *client_id = NULL;
5022 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5024 if (server->server_type == SILC_SERVER && !server->standalone) {
5025 if (!cmd->pending) {
5026 /* Send the command to router */
5028 SilcUInt16 old_ident;
5030 old_ident = silc_command_get_ident(cmd->payload);
5031 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5032 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5034 silc_server_packet_send(server, server->router->connection,
5035 SILC_PACKET_COMMAND, cmd->packet->flags,
5036 tmpbuf->data, tmpbuf->len, TRUE);
5038 /* Reprocess this packet after received reply from router */
5039 silc_server_command_pending(server, SILC_COMMAND_WATCH,
5040 silc_command_get_ident(cmd->payload),
5041 silc_server_command_watch,
5042 silc_server_command_dup(cmd));
5043 cmd->pending = TRUE;
5044 silc_command_set_ident(cmd->payload, old_ident);
5045 silc_buffer_free(tmpbuf);
5046 } else if (context2) {
5047 /* Received reply from router, just send same data to the client. */
5048 SilcServerCommandReplyContext reply = context2;
5050 silc_command_get_status(reply->payload, &status, NULL);
5051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5058 /* We are router and keep the watch list for local cell */
5060 /* Get the client ID */
5061 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5063 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5064 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5068 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5070 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5071 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5076 /* Get the client entry which must be in local list */
5077 client = silc_idlist_find_client_by_id(server->local_list,
5078 client_id, TRUE, NULL);
5080 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5081 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5087 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5088 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5089 if (!add_nick && !del_nick) {
5090 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5091 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5096 if (add_nick && add_nick_len > 128)
5097 add_nick[128] = '\0';
5098 if (del_nick && del_nick_len > 128)
5099 del_nick[128] = '\0';
5101 memset(nick, 0, sizeof(nick));
5103 /* Add new nickname to be watched in our cell */
5105 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5106 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5107 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5111 /* Hash the nick, we have the hash saved, not nicks because we can
5112 do one to one mapping to the nick from Client ID hash this way. */
5113 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5114 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5116 /* Check whether this client is already watching this nickname */
5117 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5119 /* Nickname is alredy being watched for this client */
5120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5121 SILC_STATUS_ERR_NICKNAME_IN_USE,
5126 /* Get the nickname from the watcher list and use the same key in
5127 new entries as well. If key doesn't exist then create it. */
5128 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5129 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5131 /* Add the client to the watcher list with the specified nickname hash. */
5132 silc_hash_table_add(server->watcher_list, tmp, client);
5135 /* Delete nickname from watch list */
5137 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5139 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5143 /* Hash the nick, we have the hash saved, not nicks because we can
5144 do one to one mapping to the nick from Client ID hash this way. */
5145 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5146 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5148 /* Check that this client is watching for this nickname */
5149 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5150 client, (void **)&tmp)) {
5151 /* Nickname is alredy being watched for this client */
5152 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5153 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5157 /* Delete the nickname from the watcher list. */
5158 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5160 /* Now check whether there still exists entries with this key, if not
5161 then free the key to not leak memory. */
5162 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5166 /* Distribute the watch list to backup routers too */
5167 if (server->backup) {
5169 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5170 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5171 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5172 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5174 silc_buffer_free(tmpbuf);
5177 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5181 silc_free(client_id);
5182 silc_server_command_free(cmd);
5185 /* Server side of SILCOPER command. Client uses this comand to obtain router
5186 operator privileges to this router. */
5188 SILC_SERVER_CMD_FUNC(silcoper)
5190 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5191 SilcServer server = cmd->server;
5192 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5193 unsigned char *username, *auth;
5195 SilcServerConfigAdmin *admin;
5196 SilcIDListData idata = (SilcIDListData)client;
5197 bool result = FALSE;
5198 SilcPublicKey cached_key;
5200 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5202 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5205 if (server->server_type != SILC_ROUTER) {
5206 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5207 SILC_STATUS_ERR_AUTH_FAILED, 0);
5211 /* Get the username */
5212 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5214 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5215 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5220 /* Get the admin configuration */
5221 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5222 username, client->nickname);
5224 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5225 username, client->nickname);
5227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5228 SILC_STATUS_ERR_AUTH_FAILED, 0);
5233 /* Get the authentication payload */
5234 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5236 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5237 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5242 /* Verify the authentication data. If both passphrase and public key
5243 is set then try both of them. */
5244 if (admin->passphrase)
5245 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5246 admin->passphrase, admin->passphrase_len,
5247 idata->hash, client->id, SILC_ID_CLIENT);
5248 if (!result && admin->publickeys) {
5249 cached_key = silc_server_get_public_key(server, admin->publickeys);
5252 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5253 cached_key, 0, idata->hash,
5254 client->id, SILC_ID_CLIENT);
5257 /* Authentication failed */
5258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5259 SILC_STATUS_ERR_AUTH_FAILED, 0);
5263 /* Client is now router operator */
5264 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5266 /* Update statistics */
5267 if (client->connection)
5268 server->stat.my_router_ops++;
5269 if (server->server_type == SILC_ROUTER)
5270 server->stat.router_ops++;
5272 /* Send UMODE change to primary router */
5273 if (!server->standalone)
5274 silc_server_send_notify_umode(server, server->router->connection, TRUE,
5275 client->id, client->mode);
5277 /* Check if anyone is watching this nickname */
5278 if (server->server_type == SILC_ROUTER)
5279 silc_server_check_watcher_list(server, client, NULL,
5280 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5282 /* Send reply to the sender */
5283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5287 silc_server_command_free(cmd);
5290 /* Server side of command BAN. This is used to manage the ban list of the
5291 channel. To add clients and remove clients from the ban list. */
5293 SILC_SERVER_CMD_FUNC(ban)
5295 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5296 SilcServer server = cmd->server;
5297 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5299 SilcChannelEntry channel;
5300 SilcChannelClientEntry chl;
5301 SilcChannelID *channel_id = NULL;
5302 unsigned char *id, *add, *del;
5303 SilcUInt32 id_len, tmp_len;
5304 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5306 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5309 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5311 /* Get Channel ID */
5312 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5314 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5317 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5322 /* Get channel entry. The server must know about the channel since the
5323 client is expected to be on the channel. */
5324 channel = silc_idlist_find_channel_by_id(server->local_list,
5327 channel = silc_idlist_find_channel_by_id(server->global_list,
5330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5331 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5337 /* Check whether this client is on the channel */
5338 if (!silc_server_client_on_channel(client, channel, &chl)) {
5339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5340 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5344 /* The client must be at least channel operator. */
5345 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5347 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5351 /* Get the new ban and add it to the ban list */
5352 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5354 if (!channel->ban_list)
5355 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5357 channel->ban_list = silc_realloc(channel->ban_list,
5358 sizeof(*channel->ban_list) *
5360 strlen(channel->ban_list) + 2));
5361 if (add[tmp_len - 1] == ',')
5362 add[tmp_len - 1] = '\0';
5364 strncat(channel->ban_list, add, tmp_len);
5365 strncat(channel->ban_list, ",", 1);
5368 /* Get the ban to be removed and remove it from the list */
5369 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5370 if (del && channel->ban_list) {
5371 char *start, *end, *n;
5373 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5374 silc_free(channel->ban_list);
5375 channel->ban_list = NULL;
5377 start = strstr(channel->ban_list, del);
5378 if (start && strlen(start) >= tmp_len) {
5379 end = start + tmp_len;
5380 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5381 strncat(n, channel->ban_list, start - channel->ban_list);
5382 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5384 silc_free(channel->ban_list);
5385 channel->ban_list = n;
5390 /* Send the BAN notify type to our primary router. */
5391 if (!server->standalone && (add || del))
5392 silc_server_send_notify_ban(server, server->router->connection,
5393 server->server_type == SILC_ROUTER ?
5394 TRUE : FALSE, channel, add, del);
5396 /* Send the reply back to the client */
5398 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5399 SILC_STATUS_OK, 0, ident, 2,
5401 3, channel->ban_list,
5403 strlen(channel->ban_list) -1 : 0);
5404 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5405 packet->data, packet->len, FALSE);
5407 silc_buffer_free(packet);
5410 silc_free(channel_id);
5411 silc_server_command_free(cmd);
5414 /* Server side command of LEAVE. Removes client from a channel. */
5416 SILC_SERVER_CMD_FUNC(leave)
5418 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5419 SilcServer server = cmd->server;
5420 SilcSocketConnection sock = cmd->sock;
5421 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5422 SilcChannelID *id = NULL;
5423 SilcChannelEntry channel;
5427 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5429 /* Get Channel ID */
5430 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5433 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5436 id = silc_id_payload_parse_id(tmp, len, NULL);
5438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5439 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5443 /* Get channel entry */
5444 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5446 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5448 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5449 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5455 /* Check whether this client is on the channel */
5456 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5458 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5462 /* Notify routers that they should remove this client from their list
5463 of clients on the channel. Send LEAVE notify type. */
5464 if (!server->standalone)
5465 silc_server_send_notify_leave(server, server->router->connection,
5466 server->server_type == SILC_ROUTER ?
5467 TRUE : FALSE, channel, id_entry->id);
5469 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5470 SILC_STATUS_OK, 0, 2, tmp, len);
5472 /* Remove client from channel */
5473 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5475 /* If the channel does not exist anymore we won't send anything */
5478 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5479 /* Re-generate channel key */
5480 if (!silc_server_create_channel_key(server, channel, 0))
5483 /* Send the channel key */
5484 silc_server_send_channel_key(server, NULL, channel,
5485 server->server_type == SILC_ROUTER ?
5486 FALSE : !server->standalone);
5491 silc_server_command_free(cmd);
5494 /* Server side of command USERS. Resolves clients and their USERS currently
5495 joined on the requested channel. The list of Client ID's and their modes
5496 on the channel is sent back. */
5498 SILC_SERVER_CMD_FUNC(users)
5500 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5501 SilcServer server = cmd->server;
5502 SilcChannelEntry channel;
5503 SilcChannelID *id = NULL;
5504 SilcBuffer packet, idp;
5505 unsigned char *channel_id;
5506 SilcUInt32 channel_id_len;
5507 SilcBuffer client_id_list;
5508 SilcBuffer client_mode_list;
5509 unsigned char lc[4];
5510 SilcUInt32 list_count = 0;
5511 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5514 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5516 /* Get Channel ID */
5517 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5519 /* Get channel name */
5520 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5522 if (!channel_id && !channel_name) {
5523 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5524 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5529 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5532 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5537 /* If we are server and we don't know about this channel we will send
5538 the command to our router. If we know about the channel then we also
5539 have the list of users already. */
5541 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5543 channel = silc_idlist_find_channel_by_name(server->local_list,
5544 channel_name, NULL);
5546 if (!channel || (!server->standalone && (channel->disabled ||
5547 !channel->users_resolved))) {
5548 if (server->server_type != SILC_ROUTER && !server->standalone &&
5552 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5553 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5555 /* Send USERS command */
5556 silc_server_packet_send(server, server->router->connection,
5557 SILC_PACKET_COMMAND, cmd->packet->flags,
5558 tmpbuf->data, tmpbuf->len, TRUE);
5560 /* Reprocess this packet after received reply */
5561 silc_server_command_pending(server, SILC_COMMAND_USERS,
5562 silc_command_get_ident(cmd->payload),
5563 silc_server_command_users,
5564 silc_server_command_dup(cmd));
5565 cmd->pending = TRUE;
5566 silc_command_set_ident(cmd->payload, ident);
5567 silc_buffer_free(tmpbuf);
5572 /* Check the global list as well. */
5574 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5576 channel = silc_idlist_find_channel_by_name(server->global_list,
5577 channel_name, NULL);
5579 /* Channel really does not exist */
5580 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5581 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5587 /* If the channel is private or secret do not send anything, unless the
5588 user requesting this command is on the channel or is server */
5589 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5590 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5591 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5593 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5594 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5599 /* Get the users list */
5600 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5601 &client_mode_list, &list_count)) {
5603 client_id_list = NULL;
5604 client_mode_list = NULL;
5608 SILC_PUT32_MSB(list_count, lc);
5611 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5612 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5613 SILC_STATUS_OK, 0, ident, 4,
5614 2, idp->data, idp->len,
5617 client_id_list->data : NULL,
5619 client_id_list->len : 0,
5620 5, client_mode_list ?
5621 client_mode_list->data : NULL,
5623 client_mode_list->len : 0);
5624 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5625 packet->data, packet->len, FALSE);
5627 silc_buffer_free(idp);
5628 silc_buffer_free(packet);
5630 silc_buffer_free(client_id_list);
5631 if (client_mode_list)
5632 silc_buffer_free(client_mode_list);
5636 silc_server_command_free(cmd);
5639 /* Server side of command GETKEY. This fetches the client's public key
5640 from the server where to the client is connected. */
5642 SILC_SERVER_CMD_FUNC(getkey)
5644 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5645 SilcServer server = cmd->server;
5647 SilcClientEntry client;
5648 SilcServerEntry server_entry;
5649 SilcClientID *client_id = NULL;
5650 SilcServerID *server_id = NULL;
5651 SilcIDPayload idp = NULL;
5652 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5653 unsigned char *tmp, *pkdata;
5654 SilcUInt32 tmp_len, pklen;
5655 SilcBuffer pk = NULL;
5657 SilcPublicKey public_key;
5659 SILC_LOG_DEBUG(("Start"));
5661 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5663 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5664 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5668 idp = silc_id_payload_parse(tmp, tmp_len);
5670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5671 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5676 id_type = silc_id_payload_get_type(idp);
5677 if (id_type == SILC_ID_CLIENT) {
5678 client_id = silc_id_payload_get_id(idp);
5680 /* If the client is not found from local list there is no chance it
5681 would be locally connected client so send the command further. */
5682 client = silc_idlist_find_client_by_id(server->local_list,
5683 client_id, TRUE, NULL);
5685 client = silc_idlist_find_client_by_id(server->global_list,
5686 client_id, TRUE, NULL);
5688 if ((!client && !cmd->pending && !server->standalone) ||
5689 (client && !client->connection && !cmd->pending &&
5690 !(client->mode & SILC_UMODE_DETACHED)) ||
5691 (client && !client->data.public_key && !cmd->pending)) {
5693 SilcUInt16 old_ident;
5694 SilcSocketConnection dest_sock;
5696 dest_sock = silc_server_get_client_route(server, NULL, 0,
5697 client_id, NULL, NULL);
5701 old_ident = silc_command_get_ident(cmd->payload);
5702 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5703 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5705 silc_server_packet_send(server, dest_sock,
5706 SILC_PACKET_COMMAND, cmd->packet->flags,
5707 tmpbuf->data, tmpbuf->len, TRUE);
5709 /* Reprocess this packet after received reply from router */
5710 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5711 silc_command_get_ident(cmd->payload),
5712 silc_server_command_getkey,
5713 silc_server_command_dup(cmd));
5714 cmd->pending = TRUE;
5715 silc_command_set_ident(cmd->payload, old_ident);
5716 silc_buffer_free(tmpbuf);
5721 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5722 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5727 /* The client is locally connected, just get the public key and
5728 send it back. If they key does not exist then do not send it,
5729 send just OK reply */
5730 public_key = client->data.public_key;
5735 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5736 pk = silc_buffer_alloc(4 + tmp_len);
5737 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5738 silc_buffer_format(pk,
5739 SILC_STR_UI_SHORT(tmp_len),
5740 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5741 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5747 } else if (id_type == SILC_ID_SERVER) {
5748 server_id = silc_id_payload_get_id(idp);
5750 /* If the server is not found from local list there is no chance it
5751 would be locally connected server so send the command further. */
5752 server_entry = silc_idlist_find_server_by_id(server->local_list,
5753 server_id, TRUE, NULL);
5755 server_entry = silc_idlist_find_server_by_id(server->global_list,
5756 server_id, TRUE, NULL);
5758 if (server_entry != server->id_entry &&
5759 ((!server_entry && !cmd->pending && !server->standalone) ||
5760 (server_entry && !server_entry->connection && !cmd->pending &&
5761 !server->standalone) ||
5762 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5763 !server->standalone))) {
5765 SilcUInt16 old_ident;
5767 old_ident = silc_command_get_ident(cmd->payload);
5768 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5769 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5771 silc_server_packet_send(server, server->router->connection,
5772 SILC_PACKET_COMMAND, cmd->packet->flags,
5773 tmpbuf->data, tmpbuf->len, TRUE);
5775 /* Reprocess this packet after received reply from router */
5776 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5777 silc_command_get_ident(cmd->payload),
5778 silc_server_command_getkey,
5779 silc_server_command_dup(cmd));
5780 cmd->pending = TRUE;
5781 silc_command_set_ident(cmd->payload, old_ident);
5782 silc_buffer_free(tmpbuf);
5786 if (!server_entry) {
5787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5788 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5793 /* If they key does not exist then do not send it, send just OK reply */
5794 public_key = (!server_entry->data.public_key ?
5795 (server_entry == server->id_entry ? server->public_key :
5796 NULL) : server_entry->data.public_key);
5801 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5802 pk = silc_buffer_alloc(4 + tmp_len);
5803 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5804 silc_buffer_format(pk,
5805 SILC_STR_UI_SHORT(tmp_len),
5806 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5807 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5817 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5818 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5819 SILC_STATUS_OK, 0, ident,
5823 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5824 packet->data, packet->len, FALSE);
5825 silc_buffer_free(packet);
5828 silc_buffer_free(pk);
5832 silc_id_payload_free(idp);
5833 silc_free(client_id);
5834 silc_free(server_id);
5835 silc_server_command_free(cmd);
5839 /* Private range commands, specific to this implementation */
5841 /* Server side command of CONNECT. Connects us to the specified remote
5842 server or router. */
5844 SILC_SERVER_CMD_FUNC(connect)
5846 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5847 SilcServer server = cmd->server;
5848 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5849 unsigned char *tmp, *host;
5851 SilcUInt32 port = SILC_PORT;
5853 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5855 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5858 /* Check whether client has the permissions. */
5859 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5860 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5862 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5866 if (server->server_type == SILC_ROUTER &&
5867 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5868 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5869 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5873 /* Get the remote server */
5874 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5876 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5877 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5883 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5885 SILC_GET32_MSB(port, tmp);
5887 /* Create the connection. It is done with timeout and is async. */
5888 silc_server_create_connection(server, host, port);
5890 /* Send reply to the sender */
5891 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5895 silc_server_command_free(cmd);
5898 /* Server side command of CLOSE. Closes connection to a specified server. */
5900 SILC_SERVER_CMD_FUNC(close)
5902 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5903 SilcServer server = cmd->server;
5904 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5905 SilcServerEntry server_entry;
5906 SilcSocketConnection sock;
5909 unsigned char *name;
5910 SilcUInt32 port = SILC_PORT;
5912 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5914 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5917 /* Check whether client has the permissions. */
5918 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5919 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5920 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5921 SILC_STATUS_ERR_NO_SERVER_PRIV,
5926 /* Get the remote server */
5927 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5930 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5936 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5938 SILC_GET32_MSB(port, tmp);
5940 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5941 name, port, FALSE, NULL);
5943 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5944 name, port, FALSE, NULL);
5945 if (!server_entry) {
5946 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5947 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5951 /* Send reply to the sender */
5952 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5955 /* Close the connection to the server */
5956 sock = (SilcSocketConnection)server_entry->connection;
5958 /* If we shutdown primary router connection manually then don't trigger
5959 any reconnect or backup router connections, by setting the router
5961 if (server->router == server_entry) {
5962 server->id_entry->router = NULL;
5963 server->router = NULL;
5964 server->standalone = TRUE;
5966 silc_server_free_sock_user_data(server, sock, NULL);
5967 silc_server_close_connection(server, sock);
5970 silc_server_command_free(cmd);
5973 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5974 active connections. */
5976 SILC_SERVER_CMD_FUNC(shutdown)
5978 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5979 SilcServer server = cmd->server;
5980 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5982 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5984 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5987 /* Check whether client has the permission. */
5988 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5989 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5990 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5991 SILC_STATUS_ERR_NO_SERVER_PRIV,
5996 /* Send reply to the sender */
5997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6000 /* Then, gracefully, or not, bring the server down. */
6001 silc_server_stop(server);
6005 silc_server_command_free(cmd);