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--;
3877 if (mask & SILC_UMODE_DETACHED) {
3878 if (!client->mode & SILC_UMODE_DETACHED)
3879 server->stat.my_detached++;
3881 if (client->mode & SILC_UMODE_DETACHED)
3882 server->stat.my_detached--;
3885 /* Change the mode */
3886 client->mode = mask;
3888 /* Send UMODE change to primary router */
3889 if (!server->standalone)
3890 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3891 client->id, client->mode);
3893 /* Check if anyone is watching this nickname */
3894 if (server->server_type == SILC_ROUTER)
3895 silc_server_check_watcher_list(server, client, NULL,
3896 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3899 /* Send command reply to sender */
3900 SILC_PUT32_MSB(client->mode, m);
3901 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3902 SILC_STATUS_OK, 0, ident, 1,
3904 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3905 packet->data, packet->len, FALSE);
3906 silc_buffer_free(packet);
3909 silc_server_command_free(cmd);
3912 /* Server side command of CMODE. Changes channel mode */
3914 SILC_SERVER_CMD_FUNC(cmode)
3916 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3917 SilcServer server = cmd->server;
3918 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3919 SilcIDListData idata = (SilcIDListData)client;
3920 SilcChannelID *channel_id = NULL;
3921 SilcChannelEntry channel;
3922 SilcChannelClientEntry chl;
3923 SilcBuffer packet, cidp;
3924 unsigned char *tmp, *tmp_id, *tmp_mask;
3925 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3926 SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3927 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3928 bool set_mask = FALSE;
3929 SilcPublicKey founder_key = NULL;
3930 unsigned char *fkey = NULL;
3931 SilcUInt32 fkey_len = 0;
3933 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3935 /* Get Channel ID */
3936 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3938 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3939 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3942 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3945 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3949 /* Get the channel mode mask */
3950 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3952 SILC_GET32_MSB(mode_mask, tmp_mask);
3956 /* Get channel entry */
3957 channel = silc_idlist_find_channel_by_id(server->local_list,
3960 channel = silc_idlist_find_channel_by_id(server->global_list,
3963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3964 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3970 /* Check whether this client is on the channel */
3971 if (!silc_server_client_on_channel(client, channel, &chl)) {
3972 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3973 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3977 /* Check that client has rights to change any requested channel modes */
3978 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
3980 silc_server_command_send_status_reply(
3981 cmd, SILC_COMMAND_CMODE,
3982 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
3983 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3984 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
3988 /* If mode mask was not sent as argument then merely return the current
3989 mode mask to the sender. */
3992 SILC_PUT32_MSB(channel->mode, m);
3993 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3994 SILC_STATUS_OK, 0, ident, 2,
3995 2, tmp_id, tmp_len2,
3997 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3998 packet->data, packet->len, FALSE);
3999 silc_buffer_free(packet);
4004 * Check the modes. Modes that requires nothing special operation are
4008 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4009 /* Channel uses private keys to protect traffic. Client(s) has set the
4010 key locally they want to use, server does not know that key. */
4011 /* Nothing interesting to do here */
4013 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4014 /* The mode is removed and we need to generate and distribute
4015 new channel key. Clients are not using private channel keys
4016 anymore after this. */
4018 /* Re-generate channel key */
4019 if (!silc_server_create_channel_key(server, channel, 0))
4022 /* Send the channel key. This sends it to our local clients and if
4023 we are normal server to our router as well. */
4024 silc_server_send_channel_key(server, NULL, channel,
4025 server->server_type == SILC_ROUTER ?
4026 FALSE : !server->standalone);
4028 cipher = channel->channel_key->cipher->name;
4029 hmac = (char *)silc_hmac_get_name(channel->hmac);
4033 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4034 /* User limit is set on channel */
4035 SilcUInt32 user_limit;
4037 /* Get user limit */
4038 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4040 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4041 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4042 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4046 SILC_GET32_MSB(user_limit, tmp);
4047 channel->user_limit = user_limit;
4050 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4051 /* User limit mode is unset. Remove user limit */
4052 channel->user_limit = 0;
4055 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4056 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4057 /* Passphrase has been set to channel */
4059 /* Get the passphrase */
4060 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4063 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4067 /* Save the passphrase */
4068 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4071 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4072 /* Passphrase mode is unset. remove the passphrase */
4073 silc_free(channel->passphrase);
4074 channel->passphrase = NULL;
4078 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4079 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4080 /* Cipher to use protect the traffic */
4081 SilcCipher newkey, oldkey;
4084 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4086 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4087 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4091 /* Delete old cipher and allocate the new one */
4092 if (!silc_cipher_alloc(cipher, &newkey)) {
4093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4094 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4098 oldkey = channel->channel_key;
4099 channel->channel_key = newkey;
4101 /* Re-generate channel key */
4102 if (!silc_server_create_channel_key(server, channel, 0)) {
4103 /* We don't have new key, revert to old one */
4104 channel->channel_key = oldkey;
4108 /* Remove old channel key for good */
4109 silc_cipher_free(oldkey);
4111 /* Send the channel key. This sends it to our local clients and if
4112 we are normal server to our router as well. */
4113 silc_server_send_channel_key(server, NULL, channel,
4114 server->server_type == SILC_ROUTER ?
4115 FALSE : !server->standalone);
4118 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4119 /* Cipher mode is unset. Remove the cipher and revert back to
4121 SilcCipher newkey, oldkey;
4122 cipher = channel->cipher;
4124 /* Delete old cipher and allocate default one */
4125 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4127 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4131 oldkey = channel->channel_key;
4132 channel->channel_key = newkey;
4134 /* Re-generate channel key */
4135 if (!silc_server_create_channel_key(server, channel, 0)) {
4136 /* We don't have new key, revert to old one */
4137 channel->channel_key = oldkey;
4141 /* Remove old channel key for good */
4142 silc_cipher_free(oldkey);
4144 /* Send the channel key. This sends it to our local clients and if
4145 we are normal server to our router as well. */
4146 silc_server_send_channel_key(server, NULL, channel,
4147 server->server_type == SILC_ROUTER ?
4148 FALSE : !server->standalone);
4152 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4153 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4154 /* HMAC to use protect the traffic */
4155 unsigned char hash[32];
4159 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4161 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4162 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4166 /* Delete old hmac and allocate the new one */
4167 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4168 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4169 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4173 silc_hmac_free(channel->hmac);
4174 channel->hmac = newhmac;
4176 /* Set the HMAC key out of current channel key. The client must do
4178 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4179 channel->key_len / 8, hash);
4180 silc_hmac_set_key(channel->hmac, hash,
4181 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4182 memset(hash, 0, sizeof(hash));
4185 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4186 /* Hmac mode is unset. Remove the hmac and revert back to
4189 unsigned char hash[32];
4190 hmac = channel->hmac_name;
4192 /* Delete old hmac and allocate default one */
4193 silc_hmac_free(channel->hmac);
4194 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4195 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4196 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4200 silc_hmac_free(channel->hmac);
4201 channel->hmac = newhmac;
4203 /* Set the HMAC key out of current channel key. The client must do
4205 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4206 channel->key_len / 8,
4208 silc_hmac_set_key(channel->hmac, hash,
4209 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4210 memset(hash, 0, sizeof(hash));
4214 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4215 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4216 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4217 /* Set the founder authentication */
4218 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4220 silc_server_command_send_status_reply(
4221 cmd, SILC_COMMAND_CMODE,
4222 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4226 /* Verify the payload before setting the mode */
4227 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4228 idata->public_key, 0, server->sha1hash,
4229 client->id, SILC_ID_CLIENT)) {
4230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4231 SILC_STATUS_ERR_AUTH_FAILED,
4236 /* Save the public key */
4237 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4238 if (!channel->founder_key) {
4239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4240 SILC_STATUS_ERR_AUTH_FAILED,
4245 founder_key = channel->founder_key;
4246 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4248 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4249 SILC_STATUS_ERR_AUTH_FAILED,
4256 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4257 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4258 if (channel->founder_key)
4259 silc_pkcs_public_key_free(channel->founder_key);
4260 channel->founder_key = NULL;
4265 /* Finally, set the mode */
4266 channel->mode = mode_mask;
4268 /* Send CMODE_CHANGE notify. */
4269 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4270 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4271 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4272 cidp->data, cidp->len,
4274 cipher, cipher ? strlen(cipher) : 0,
4275 hmac, hmac ? strlen(hmac) : 0,
4276 passphrase, passphrase ?
4277 strlen(passphrase) : 0,
4280 /* Set CMODE notify type to network */
4281 if (!server->standalone)
4282 silc_server_send_notify_cmode(server, server->router->connection,
4283 server->server_type == SILC_ROUTER ?
4284 TRUE : FALSE, channel,
4285 mode_mask, client->id, SILC_ID_CLIENT,
4286 cipher, hmac, passphrase, founder_key);
4288 /* Send command reply to sender */
4289 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4290 SILC_STATUS_OK, 0, ident, 2,
4291 2, tmp_id, tmp_len2,
4293 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4294 packet->data, packet->len, FALSE);
4296 silc_buffer_free(packet);
4297 silc_buffer_free(cidp);
4301 silc_free(channel_id);
4302 silc_server_command_free(cmd);
4305 /* Server side of CUMODE command. Changes client's mode on a channel. */
4307 SILC_SERVER_CMD_FUNC(cumode)
4309 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4310 SilcServer server = cmd->server;
4311 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4312 SilcIDListData idata = (SilcIDListData)client;
4313 SilcChannelID *channel_id;
4314 SilcClientID *client_id;
4315 SilcChannelEntry channel;
4316 SilcClientEntry target_client;
4317 SilcChannelClientEntry chl;
4318 SilcBuffer packet, idp;
4319 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4320 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4322 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4323 SilcPublicKey founder_key = NULL;
4324 unsigned char *fkey = NULL;
4325 SilcUInt32 fkey_len = 0;
4327 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4329 /* Get Channel ID */
4330 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4333 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4336 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4338 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4339 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4343 /* Get channel entry */
4344 channel = silc_idlist_find_channel_by_id(server->local_list,
4347 channel = silc_idlist_find_channel_by_id(server->global_list,
4350 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4351 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4357 /* Check whether sender is on the channel */
4358 if (!silc_server_client_on_channel(client, channel, &chl)) {
4359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4360 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4363 sender_mask = chl->mode;
4365 /* Get the target client's channel mode mask */
4366 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4369 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4373 SILC_GET32_MSB(target_mask, tmp_mask);
4375 /* Get target Client ID */
4376 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4378 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4379 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4382 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4384 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4385 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4389 /* Get target client's entry */
4390 target_client = silc_idlist_find_client_by_id(server->local_list,
4391 client_id, TRUE, NULL);
4392 if (!target_client) {
4393 target_client = silc_idlist_find_client_by_id(server->global_list,
4394 client_id, TRUE, NULL);
4397 if (target_client != client &&
4398 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4399 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4400 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4401 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4405 /* Check whether target client is on the channel */
4406 if (target_client != client) {
4407 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4409 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4418 /* If the target client is founder, no one else can change their mode
4420 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4422 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4427 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4428 if (target_client != client) {
4429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4430 SILC_STATUS_ERR_NOT_YOU, 0);
4434 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4435 /* The client tries to claim the founder rights. */
4436 unsigned char *tmp_auth;
4437 SilcUInt32 tmp_auth_len;
4438 SilcChannelClientEntry chl2;
4439 SilcHashTableList htl;
4441 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4442 !channel->founder_key || !idata->public_key ||
4443 !silc_pkcs_public_key_compare(channel->founder_key,
4444 idata->public_key)) {
4445 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4446 SILC_STATUS_ERR_AUTH_FAILED, 0);
4450 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4453 SILC_STATUS_ERR_AUTH_FAILED, 0);
4457 /* Verify the authentication payload */
4458 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4459 channel->founder_key, 0, server->sha1hash,
4460 client->id, SILC_ID_CLIENT)) {
4461 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4462 SILC_STATUS_ERR_AUTH_FAILED, 0);
4467 founder_key = channel->founder_key;
4468 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4470 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4471 SILC_STATUS_ERR_AUTH_FAILED, 0);
4475 /* There cannot be anyone else as founder on the channel now. This
4476 client is definitely the founder due to this authentication */
4477 silc_hash_table_list(channel->user_list, &htl);
4478 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4479 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4480 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4481 silc_server_force_cumode_change(server, NULL, channel, chl2,
4485 silc_hash_table_list_reset(&htl);
4487 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4490 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4491 if (target_client == client) {
4492 /* Remove channel founder rights from itself */
4493 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4496 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4497 SILC_STATUS_ERR_NOT_YOU, 0);
4503 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4504 /* Promote to operator */
4505 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4506 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4507 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4508 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4509 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4514 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4518 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4519 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4520 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4521 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4522 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4527 /* Demote to normal user */
4528 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4533 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4534 if (target_client != client) {
4535 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4536 SILC_STATUS_ERR_NOT_YOU, 0);
4540 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4541 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4545 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4546 if (target_client != client) {
4547 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4548 SILC_STATUS_ERR_NOT_YOU, 0);
4552 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4557 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4558 if (target_client != client) {
4559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4560 SILC_STATUS_ERR_NOT_YOU, 0);
4564 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4565 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4569 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4570 if (target_client != client) {
4571 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4572 SILC_STATUS_ERR_NOT_YOU, 0);
4576 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4581 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4582 if (target_client != client) {
4583 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4584 SILC_STATUS_ERR_NOT_YOU, 0);
4588 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4589 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4593 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4594 if (target_client != client) {
4595 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4596 SILC_STATUS_ERR_NOT_YOU, 0);
4600 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4605 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4606 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4607 if (client == target_client) {
4608 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4609 SILC_STATUS_ERR_PERM_DENIED, 0);
4612 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4616 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4617 if (client == target_client) {
4618 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4619 SILC_STATUS_ERR_PERM_DENIED, 0);
4622 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4627 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4628 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4630 /* Send notify to channel, notify only if mode was actually changed. */
4632 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4633 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4634 idp->data, idp->len,
4639 /* Set CUMODE notify type to network */
4640 if (!server->standalone)
4641 silc_server_send_notify_cumode(server, server->router->connection,
4642 server->server_type == SILC_ROUTER ?
4643 TRUE : FALSE, channel,
4644 target_mask, client->id,
4646 target_client->id, founder_key);
4649 /* Send command reply to sender */
4650 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4651 SILC_STATUS_OK, 0, ident, 3,
4653 3, tmp_ch_id, tmp_ch_len,
4654 4, tmp_id, tmp_len);
4655 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4656 packet->data, packet->len, FALSE);
4658 silc_buffer_free(packet);
4659 silc_free(channel_id);
4660 silc_free(client_id);
4661 silc_buffer_free(idp);
4665 silc_server_command_free(cmd);
4668 /* Server side of KICK command. Kicks client out of channel. */
4670 SILC_SERVER_CMD_FUNC(kick)
4672 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4673 SilcServer server = cmd->server;
4674 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4675 SilcClientEntry target_client;
4676 SilcChannelID *channel_id;
4677 SilcClientID *client_id;
4678 SilcChannelEntry channel;
4679 SilcChannelClientEntry chl;
4681 SilcUInt32 tmp_len, target_idp_len;
4682 unsigned char *tmp, *comment, *target_idp;
4684 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4686 /* Get Channel ID */
4687 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4690 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4693 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4696 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4700 /* Get channel entry */
4701 channel = silc_idlist_find_channel_by_id(server->local_list,
4704 channel = silc_idlist_find_channel_by_id(server->local_list,
4707 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4708 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4714 /* Check whether sender is on the channel */
4715 if (!silc_server_client_on_channel(client, channel, &chl)) {
4716 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4717 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4721 /* Check that the kicker is channel operator or channel founder */
4722 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4723 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4724 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4725 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4729 /* Get target Client ID */
4730 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4732 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4733 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4736 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4739 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4743 /* Get target client's entry */
4744 target_client = silc_idlist_find_client_by_id(server->local_list,
4745 client_id, TRUE, NULL);
4746 if (!target_client) {
4747 target_client = silc_idlist_find_client_by_id(server->global_list,
4748 client_id, TRUE, NULL);
4751 /* Check whether target client is on the channel */
4752 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4754 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4759 /* Check that the target client is not channel founder. Channel founder
4760 cannot be kicked from the channel. */
4761 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4763 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4770 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4774 /* Send command reply to sender */
4775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4778 /* Send KICKED notify to local clients on the channel */
4779 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4780 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4781 SILC_NOTIFY_TYPE_KICKED, 3,
4782 target_idp, target_idp_len,
4783 comment, comment ? strlen(comment) : 0,
4784 idp->data, idp->len);
4785 silc_buffer_free(idp);
4787 /* Remove the client from the channel. If the channel does not exist
4788 after removing the client then the client kicked itself off the channel
4789 and we don't have to send anything after that. */
4790 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4791 target_client, FALSE))
4794 /* Send KICKED notify to primary route */
4795 if (!server->standalone)
4796 silc_server_send_notify_kicked(server, server->router->connection,
4797 server->server_type == SILC_ROUTER ?
4798 TRUE : FALSE, channel,
4799 target_client->id, client->id, comment);
4801 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4802 /* Re-generate channel key */
4803 if (!silc_server_create_channel_key(server, channel, 0))
4806 /* Send the channel key to the channel. The key of course is not sent
4807 to the client who was kicked off the channel. */
4808 silc_server_send_channel_key(server, target_client->connection, channel,
4809 server->server_type == SILC_ROUTER ?
4810 FALSE : !server->standalone);
4814 silc_server_command_free(cmd);
4817 /* Server side of OPER command. Client uses this comand to obtain server
4818 operator privileges to this server/router. */
4820 SILC_SERVER_CMD_FUNC(oper)
4822 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4823 SilcServer server = cmd->server;
4824 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4825 unsigned char *username, *auth;
4827 SilcServerConfigAdmin *admin;
4828 SilcIDListData idata = (SilcIDListData)client;
4829 bool result = FALSE;
4830 SilcPublicKey cached_key;
4832 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4834 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4837 /* Get the username */
4838 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4840 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4841 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4846 /* Get the admin configuration */
4847 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4848 username, client->nickname);
4850 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4851 username, client->nickname);
4853 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4854 SILC_STATUS_ERR_AUTH_FAILED,
4860 /* Get the authentication payload */
4861 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4863 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4864 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4869 /* Verify the authentication data. If both passphrase and public key
4870 is set then try both of them. */
4871 if (admin->passphrase)
4872 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4873 admin->passphrase, admin->passphrase_len,
4874 idata->hash, client->id, SILC_ID_CLIENT);
4875 if (!result && admin->publickeys) {
4876 cached_key = silc_server_get_public_key(server, admin->publickeys);
4879 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4880 cached_key, 0, idata->hash,
4881 client->id, SILC_ID_CLIENT);
4884 /* Authentication failed */
4885 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4886 SILC_STATUS_ERR_AUTH_FAILED,
4891 /* Client is now server operator */
4892 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4894 /* Update statistics */
4895 if (client->connection)
4896 server->stat.my_server_ops++;
4897 if (server->server_type == SILC_ROUTER)
4898 server->stat.server_ops++;
4900 /* Send UMODE change to primary router */
4901 if (!server->standalone)
4902 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4903 client->id, client->mode);
4905 /* Check if anyone is watching this nickname */
4906 if (server->server_type == SILC_ROUTER)
4907 silc_server_check_watcher_list(server, client, NULL,
4908 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4910 /* Send reply to the sender */
4911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4915 silc_server_command_free(cmd);
4918 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4920 QuitInternal q = (QuitInternal)context;
4921 SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4923 /* If there is pending outgoing data for the client then purge it
4924 to the network before closing connection. */
4925 silc_server_packet_queue_purge(q->server, q->sock);
4927 /* Close the connection on our side */
4928 client->router = NULL;
4929 client->connection = NULL;
4930 q->sock->user_data = NULL;
4931 silc_server_close_connection(q->server, q->sock);
4936 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4938 QuitInternal q = (QuitInternal)context;
4939 SilcClientID *client_id = (SilcClientID *)q->sock;
4940 SilcClientEntry client;
4942 SILC_LOG_DEBUG(("Start"));
4944 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4947 if (client && client->mode & SILC_UMODE_DETACHED)
4948 silc_server_free_client_data(q->server, NULL, client, TRUE,
4951 silc_free(client_id);
4955 /* Server side of DETACH command. Detached the client from the network
4956 by closing the connection but preserving the session. */
4958 SILC_SERVER_CMD_FUNC(detach)
4960 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4961 SilcServer server = cmd->server;
4962 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4965 if (server->config->detach_disabled) {
4966 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4967 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
4971 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4974 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4976 /* Send the user mode notify to notify that client is detached */
4977 client->mode |= SILC_UMODE_DETACHED;
4978 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4979 client->last_command = 0;
4980 client->fast_command = 0;
4981 if (!server->standalone)
4982 silc_server_send_notify_umode(server, server->router->connection,
4983 server->server_type == SILC_SERVER ?
4984 FALSE : TRUE, client->id, client->mode);
4986 /* Check if anyone is watching this nickname */
4987 if (server->server_type == SILC_ROUTER)
4988 silc_server_check_watcher_list(server, client, NULL,
4989 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4991 q = silc_calloc(1, sizeof(*q));
4993 q->sock = cmd->sock;
4994 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4995 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4997 if (server->config->detach_timeout) {
4998 q = silc_calloc(1, sizeof(*q));
5000 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5001 silc_schedule_task_add(server->schedule, 0,
5002 silc_server_command_detach_timeout,
5003 q, server->config->detach_timeout * 60,
5004 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5007 /* Send reply to the sender */
5008 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5012 silc_server_command_free(cmd);
5015 /* Server side of WATCH command. */
5017 SILC_SERVER_CMD_FUNC(watch)
5019 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5020 SilcServer server = cmd->server;
5021 char *add_nick, *del_nick;
5022 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5024 unsigned char hash[16], *tmp;
5025 SilcClientEntry client;
5026 SilcClientID *client_id = NULL;
5028 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5030 if (server->server_type == SILC_SERVER && !server->standalone) {
5031 if (!cmd->pending) {
5032 /* Send the command to router */
5034 SilcUInt16 old_ident;
5036 old_ident = silc_command_get_ident(cmd->payload);
5037 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5038 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5040 silc_server_packet_send(server, server->router->connection,
5041 SILC_PACKET_COMMAND, cmd->packet->flags,
5042 tmpbuf->data, tmpbuf->len, TRUE);
5044 /* Reprocess this packet after received reply from router */
5045 silc_server_command_pending(server, SILC_COMMAND_WATCH,
5046 silc_command_get_ident(cmd->payload),
5047 silc_server_command_watch,
5048 silc_server_command_dup(cmd));
5049 cmd->pending = TRUE;
5050 silc_command_set_ident(cmd->payload, old_ident);
5051 silc_buffer_free(tmpbuf);
5052 } else if (context2) {
5053 /* Received reply from router, just send same data to the client. */
5054 SilcServerCommandReplyContext reply = context2;
5056 silc_command_get_status(reply->payload, &status, NULL);
5057 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5064 /* We are router and keep the watch list for local cell */
5066 /* Get the client ID */
5067 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5069 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5070 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5074 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5076 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5077 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5082 /* Get the client entry which must be in local list */
5083 client = silc_idlist_find_client_by_id(server->local_list,
5084 client_id, TRUE, NULL);
5086 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5087 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5093 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5094 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5095 if (!add_nick && !del_nick) {
5096 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5097 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5102 if (add_nick && add_nick_len > 128)
5103 add_nick[128] = '\0';
5104 if (del_nick && del_nick_len > 128)
5105 del_nick[128] = '\0';
5107 memset(nick, 0, sizeof(nick));
5109 /* Add new nickname to be watched in our cell */
5111 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5112 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5113 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5117 /* Hash the nick, we have the hash saved, not nicks because we can
5118 do one to one mapping to the nick from Client ID hash this way. */
5119 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5120 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5122 /* Check whether this client is already watching this nickname */
5123 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5125 /* Nickname is alredy being watched for this client */
5126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5127 SILC_STATUS_ERR_NICKNAME_IN_USE,
5132 /* Get the nickname from the watcher list and use the same key in
5133 new entries as well. If key doesn't exist then create it. */
5134 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5135 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5137 /* Add the client to the watcher list with the specified nickname hash. */
5138 silc_hash_table_add(server->watcher_list, tmp, client);
5141 /* Delete nickname from watch list */
5143 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5144 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5145 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5149 /* Hash the nick, we have the hash saved, not nicks because we can
5150 do one to one mapping to the nick from Client ID hash this way. */
5151 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5152 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5154 /* Check that this client is watching for this nickname */
5155 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5156 client, (void **)&tmp)) {
5157 /* Nickname is alredy being watched for this client */
5158 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5159 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5163 /* Delete the nickname from the watcher list. */
5164 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5166 /* Now check whether there still exists entries with this key, if not
5167 then free the key to not leak memory. */
5168 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5172 /* Distribute the watch list to backup routers too */
5173 if (server->backup) {
5175 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5176 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5177 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5178 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5180 silc_buffer_free(tmpbuf);
5183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5187 silc_free(client_id);
5188 silc_server_command_free(cmd);
5191 /* Server side of SILCOPER command. Client uses this comand to obtain router
5192 operator privileges to this router. */
5194 SILC_SERVER_CMD_FUNC(silcoper)
5196 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5197 SilcServer server = cmd->server;
5198 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5199 unsigned char *username, *auth;
5201 SilcServerConfigAdmin *admin;
5202 SilcIDListData idata = (SilcIDListData)client;
5203 bool result = FALSE;
5204 SilcPublicKey cached_key;
5206 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5208 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5211 if (server->server_type != SILC_ROUTER) {
5212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5213 SILC_STATUS_ERR_AUTH_FAILED, 0);
5217 /* Get the username */
5218 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5220 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5221 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5226 /* Get the admin configuration */
5227 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5228 username, client->nickname);
5230 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5231 username, client->nickname);
5233 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5234 SILC_STATUS_ERR_AUTH_FAILED, 0);
5239 /* Get the authentication payload */
5240 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5243 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5248 /* Verify the authentication data. If both passphrase and public key
5249 is set then try both of them. */
5250 if (admin->passphrase)
5251 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5252 admin->passphrase, admin->passphrase_len,
5253 idata->hash, client->id, SILC_ID_CLIENT);
5254 if (!result && admin->publickeys) {
5255 cached_key = silc_server_get_public_key(server, admin->publickeys);
5258 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5259 cached_key, 0, idata->hash,
5260 client->id, SILC_ID_CLIENT);
5263 /* Authentication failed */
5264 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5265 SILC_STATUS_ERR_AUTH_FAILED, 0);
5269 /* Client is now router operator */
5270 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5272 /* Update statistics */
5273 if (client->connection)
5274 server->stat.my_router_ops++;
5275 if (server->server_type == SILC_ROUTER)
5276 server->stat.router_ops++;
5278 /* Send UMODE change to primary router */
5279 if (!server->standalone)
5280 silc_server_send_notify_umode(server, server->router->connection, TRUE,
5281 client->id, client->mode);
5283 /* Check if anyone is watching this nickname */
5284 if (server->server_type == SILC_ROUTER)
5285 silc_server_check_watcher_list(server, client, NULL,
5286 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5288 /* Send reply to the sender */
5289 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5293 silc_server_command_free(cmd);
5296 /* Server side of command BAN. This is used to manage the ban list of the
5297 channel. To add clients and remove clients from the ban list. */
5299 SILC_SERVER_CMD_FUNC(ban)
5301 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5302 SilcServer server = cmd->server;
5303 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5305 SilcChannelEntry channel;
5306 SilcChannelClientEntry chl;
5307 SilcChannelID *channel_id = NULL;
5308 unsigned char *id, *add, *del;
5309 SilcUInt32 id_len, tmp_len;
5310 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5312 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5315 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5317 /* Get Channel ID */
5318 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5320 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5322 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5323 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5328 /* Get channel entry. The server must know about the channel since the
5329 client is expected to be on the channel. */
5330 channel = silc_idlist_find_channel_by_id(server->local_list,
5333 channel = silc_idlist_find_channel_by_id(server->global_list,
5336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5337 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5343 /* Check whether this client is on the channel */
5344 if (!silc_server_client_on_channel(client, channel, &chl)) {
5345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5346 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5350 /* The client must be at least channel operator. */
5351 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5353 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5357 /* Get the new ban and add it to the ban list */
5358 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5360 if (!channel->ban_list)
5361 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5363 channel->ban_list = silc_realloc(channel->ban_list,
5364 sizeof(*channel->ban_list) *
5366 strlen(channel->ban_list) + 2));
5367 if (add[tmp_len - 1] == ',')
5368 add[tmp_len - 1] = '\0';
5370 strncat(channel->ban_list, add, tmp_len);
5371 strncat(channel->ban_list, ",", 1);
5374 /* Get the ban to be removed and remove it from the list */
5375 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5376 if (del && channel->ban_list) {
5377 char *start, *end, *n;
5379 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5380 silc_free(channel->ban_list);
5381 channel->ban_list = NULL;
5383 start = strstr(channel->ban_list, del);
5384 if (start && strlen(start) >= tmp_len) {
5385 end = start + tmp_len;
5386 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5387 strncat(n, channel->ban_list, start - channel->ban_list);
5388 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5390 silc_free(channel->ban_list);
5391 channel->ban_list = n;
5396 /* Send the BAN notify type to our primary router. */
5397 if (!server->standalone && (add || del))
5398 silc_server_send_notify_ban(server, server->router->connection,
5399 server->server_type == SILC_ROUTER ?
5400 TRUE : FALSE, channel, add, del);
5402 /* Send the reply back to the client */
5404 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5405 SILC_STATUS_OK, 0, ident, 2,
5407 3, channel->ban_list,
5409 strlen(channel->ban_list) -1 : 0);
5410 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5411 packet->data, packet->len, FALSE);
5413 silc_buffer_free(packet);
5416 silc_free(channel_id);
5417 silc_server_command_free(cmd);
5420 /* Server side command of LEAVE. Removes client from a channel. */
5422 SILC_SERVER_CMD_FUNC(leave)
5424 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5425 SilcServer server = cmd->server;
5426 SilcSocketConnection sock = cmd->sock;
5427 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5428 SilcChannelID *id = NULL;
5429 SilcChannelEntry channel;
5433 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5435 /* Get Channel ID */
5436 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5439 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5442 id = silc_id_payload_parse_id(tmp, len, NULL);
5444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5445 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5449 /* Get channel entry */
5450 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5452 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5455 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5461 /* Check whether this client is on the channel */
5462 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5464 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5468 /* Notify routers that they should remove this client from their list
5469 of clients on the channel. Send LEAVE notify type. */
5470 if (!server->standalone)
5471 silc_server_send_notify_leave(server, server->router->connection,
5472 server->server_type == SILC_ROUTER ?
5473 TRUE : FALSE, channel, id_entry->id);
5475 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5476 SILC_STATUS_OK, 0, 2, tmp, len);
5478 /* Remove client from channel */
5479 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5481 /* If the channel does not exist anymore we won't send anything */
5484 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5485 /* Re-generate channel key */
5486 if (!silc_server_create_channel_key(server, channel, 0))
5489 /* Send the channel key */
5490 silc_server_send_channel_key(server, NULL, channel,
5491 server->server_type == SILC_ROUTER ?
5492 FALSE : !server->standalone);
5497 silc_server_command_free(cmd);
5500 /* Server side of command USERS. Resolves clients and their USERS currently
5501 joined on the requested channel. The list of Client ID's and their modes
5502 on the channel is sent back. */
5504 SILC_SERVER_CMD_FUNC(users)
5506 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5507 SilcServer server = cmd->server;
5508 SilcChannelEntry channel;
5509 SilcChannelID *id = NULL;
5510 SilcBuffer packet, idp;
5511 unsigned char *channel_id;
5512 SilcUInt32 channel_id_len;
5513 SilcBuffer client_id_list;
5514 SilcBuffer client_mode_list;
5515 unsigned char lc[4];
5516 SilcUInt32 list_count = 0;
5517 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5520 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5522 /* Get Channel ID */
5523 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5525 /* Get channel name */
5526 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5528 if (!channel_id && !channel_name) {
5529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5530 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5535 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5537 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5538 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5543 /* If we are server and we don't know about this channel we will send
5544 the command to our router. If we know about the channel then we also
5545 have the list of users already. */
5547 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5549 channel = silc_idlist_find_channel_by_name(server->local_list,
5550 channel_name, NULL);
5552 if (!channel || (!server->standalone && (channel->disabled ||
5553 !channel->users_resolved))) {
5554 if (server->server_type != SILC_ROUTER && !server->standalone &&
5558 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5559 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5561 /* Send USERS command */
5562 silc_server_packet_send(server, server->router->connection,
5563 SILC_PACKET_COMMAND, cmd->packet->flags,
5564 tmpbuf->data, tmpbuf->len, TRUE);
5566 /* Reprocess this packet after received reply */
5567 silc_server_command_pending(server, SILC_COMMAND_USERS,
5568 silc_command_get_ident(cmd->payload),
5569 silc_server_command_users,
5570 silc_server_command_dup(cmd));
5571 cmd->pending = TRUE;
5572 silc_command_set_ident(cmd->payload, ident);
5573 silc_buffer_free(tmpbuf);
5578 /* Check the global list as well. */
5580 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5582 channel = silc_idlist_find_channel_by_name(server->global_list,
5583 channel_name, NULL);
5585 /* Channel really does not exist */
5586 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5587 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5593 /* If the channel is private or secret do not send anything, unless the
5594 user requesting this command is on the channel or is server */
5595 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5596 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5597 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5600 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5605 /* Get the users list */
5606 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5607 &client_mode_list, &list_count)) {
5609 client_id_list = NULL;
5610 client_mode_list = NULL;
5614 SILC_PUT32_MSB(list_count, lc);
5617 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5618 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5619 SILC_STATUS_OK, 0, ident, 4,
5620 2, idp->data, idp->len,
5623 client_id_list->data : NULL,
5625 client_id_list->len : 0,
5626 5, client_mode_list ?
5627 client_mode_list->data : NULL,
5629 client_mode_list->len : 0);
5630 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5631 packet->data, packet->len, FALSE);
5633 silc_buffer_free(idp);
5634 silc_buffer_free(packet);
5636 silc_buffer_free(client_id_list);
5637 if (client_mode_list)
5638 silc_buffer_free(client_mode_list);
5642 silc_server_command_free(cmd);
5645 /* Server side of command GETKEY. This fetches the client's public key
5646 from the server where to the client is connected. */
5648 SILC_SERVER_CMD_FUNC(getkey)
5650 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5651 SilcServer server = cmd->server;
5653 SilcClientEntry client;
5654 SilcServerEntry server_entry;
5655 SilcClientID *client_id = NULL;
5656 SilcServerID *server_id = NULL;
5657 SilcIDPayload idp = NULL;
5658 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5659 unsigned char *tmp, *pkdata;
5660 SilcUInt32 tmp_len, pklen;
5661 SilcBuffer pk = NULL;
5663 SilcPublicKey public_key;
5665 SILC_LOG_DEBUG(("Start"));
5667 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5670 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5674 idp = silc_id_payload_parse(tmp, tmp_len);
5676 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5677 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5682 id_type = silc_id_payload_get_type(idp);
5683 if (id_type == SILC_ID_CLIENT) {
5684 client_id = silc_id_payload_get_id(idp);
5686 /* If the client is not found from local list there is no chance it
5687 would be locally connected client so send the command further. */
5688 client = silc_idlist_find_client_by_id(server->local_list,
5689 client_id, TRUE, NULL);
5691 client = silc_idlist_find_client_by_id(server->global_list,
5692 client_id, TRUE, NULL);
5694 if ((!client && !cmd->pending && !server->standalone) ||
5695 (client && !client->connection && !cmd->pending &&
5696 !(client->mode & SILC_UMODE_DETACHED)) ||
5697 (client && !client->data.public_key && !cmd->pending)) {
5699 SilcUInt16 old_ident;
5700 SilcSocketConnection dest_sock;
5702 dest_sock = silc_server_get_client_route(server, NULL, 0,
5703 client_id, NULL, NULL);
5707 old_ident = silc_command_get_ident(cmd->payload);
5708 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5709 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5711 silc_server_packet_send(server, dest_sock,
5712 SILC_PACKET_COMMAND, cmd->packet->flags,
5713 tmpbuf->data, tmpbuf->len, TRUE);
5715 /* Reprocess this packet after received reply from router */
5716 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5717 silc_command_get_ident(cmd->payload),
5718 silc_server_command_getkey,
5719 silc_server_command_dup(cmd));
5720 cmd->pending = TRUE;
5721 silc_command_set_ident(cmd->payload, old_ident);
5722 silc_buffer_free(tmpbuf);
5727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5728 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5733 /* The client is locally connected, just get the public key and
5734 send it back. If they key does not exist then do not send it,
5735 send just OK reply */
5736 public_key = client->data.public_key;
5741 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5742 pk = silc_buffer_alloc(4 + tmp_len);
5743 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5744 silc_buffer_format(pk,
5745 SILC_STR_UI_SHORT(tmp_len),
5746 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5747 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5753 } else if (id_type == SILC_ID_SERVER) {
5754 server_id = silc_id_payload_get_id(idp);
5756 /* If the server is not found from local list there is no chance it
5757 would be locally connected server so send the command further. */
5758 server_entry = silc_idlist_find_server_by_id(server->local_list,
5759 server_id, TRUE, NULL);
5761 server_entry = silc_idlist_find_server_by_id(server->global_list,
5762 server_id, TRUE, NULL);
5764 if (server_entry != server->id_entry &&
5765 ((!server_entry && !cmd->pending && !server->standalone) ||
5766 (server_entry && !server_entry->connection && !cmd->pending &&
5767 !server->standalone) ||
5768 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5769 !server->standalone))) {
5771 SilcUInt16 old_ident;
5773 old_ident = silc_command_get_ident(cmd->payload);
5774 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5775 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5777 silc_server_packet_send(server, server->router->connection,
5778 SILC_PACKET_COMMAND, cmd->packet->flags,
5779 tmpbuf->data, tmpbuf->len, TRUE);
5781 /* Reprocess this packet after received reply from router */
5782 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5783 silc_command_get_ident(cmd->payload),
5784 silc_server_command_getkey,
5785 silc_server_command_dup(cmd));
5786 cmd->pending = TRUE;
5787 silc_command_set_ident(cmd->payload, old_ident);
5788 silc_buffer_free(tmpbuf);
5792 if (!server_entry) {
5793 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5794 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5799 /* If they key does not exist then do not send it, send just OK reply */
5800 public_key = (!server_entry->data.public_key ?
5801 (server_entry == server->id_entry ? server->public_key :
5802 NULL) : server_entry->data.public_key);
5807 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5808 pk = silc_buffer_alloc(4 + tmp_len);
5809 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5810 silc_buffer_format(pk,
5811 SILC_STR_UI_SHORT(tmp_len),
5812 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5813 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5823 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5824 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5825 SILC_STATUS_OK, 0, ident,
5829 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5830 packet->data, packet->len, FALSE);
5831 silc_buffer_free(packet);
5834 silc_buffer_free(pk);
5838 silc_id_payload_free(idp);
5839 silc_free(client_id);
5840 silc_free(server_id);
5841 silc_server_command_free(cmd);
5845 /* Private range commands, specific to this implementation */
5847 /* Server side command of CONNECT. Connects us to the specified remote
5848 server or router. */
5850 SILC_SERVER_CMD_FUNC(connect)
5852 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5853 SilcServer server = cmd->server;
5854 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5855 unsigned char *tmp, *host;
5857 SilcUInt32 port = SILC_PORT;
5859 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5861 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5864 /* Check whether client has the permissions. */
5865 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5866 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5867 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5868 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5872 if (server->server_type == SILC_ROUTER &&
5873 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5874 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5875 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5879 /* Get the remote server */
5880 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5883 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5889 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5891 SILC_GET32_MSB(port, tmp);
5893 /* Create the connection. It is done with timeout and is async. */
5894 silc_server_create_connection(server, host, port);
5896 /* Send reply to the sender */
5897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5901 silc_server_command_free(cmd);
5904 /* Server side command of CLOSE. Closes connection to a specified server. */
5906 SILC_SERVER_CMD_FUNC(close)
5908 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5909 SilcServer server = cmd->server;
5910 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5911 SilcServerEntry server_entry;
5912 SilcSocketConnection sock;
5915 unsigned char *name;
5916 SilcUInt32 port = SILC_PORT;
5918 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5920 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5923 /* Check whether client has the permissions. */
5924 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5925 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5927 SILC_STATUS_ERR_NO_SERVER_PRIV,
5932 /* Get the remote server */
5933 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5935 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5936 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5942 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5944 SILC_GET32_MSB(port, tmp);
5946 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5947 name, port, FALSE, NULL);
5949 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5950 name, port, FALSE, NULL);
5951 if (!server_entry) {
5952 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5953 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5957 /* Send reply to the sender */
5958 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5961 /* Close the connection to the server */
5962 sock = (SilcSocketConnection)server_entry->connection;
5964 /* If we shutdown primary router connection manually then don't trigger
5965 any reconnect or backup router connections, by setting the router
5967 if (server->router == server_entry) {
5968 server->id_entry->router = NULL;
5969 server->router = NULL;
5970 server->standalone = TRUE;
5972 silc_server_free_sock_user_data(server, sock, NULL);
5973 silc_server_close_connection(server, sock);
5976 silc_server_command_free(cmd);
5979 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5980 active connections. */
5982 SILC_SERVER_CMD_FUNC(shutdown)
5984 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5985 SilcServer server = cmd->server;
5986 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5988 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5990 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5993 /* Check whether client has the permission. */
5994 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5995 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5996 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5997 SILC_STATUS_ERR_NO_SERVER_PRIV,
6002 /* Send reply to the sender */
6003 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6006 /* Then, gracefully, or not, bring the server down. */
6007 silc_server_stop(server);
6011 silc_server_command_free(cmd);