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_buffer_free(packet->buffer);
205 silc_packet_context_free(packet);
206 silc_socket_free(ctx->sock);
210 ctx->args = silc_command_get_args(ctx->payload);
212 /* Get the command */
213 command = silc_command_get(ctx->payload);
214 for (cmd = silc_command_list; cmd->cb; cmd++)
215 if (cmd->cmd == command)
218 if (!cmd || !cmd->cb) {
219 silc_server_command_send_status_reply(ctx, command,
220 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
221 silc_server_command_free(ctx);
225 /* Execute client's commands always with timeout. Normally they are
226 executed with zero (0) timeout but if client is sending command more
227 frequently than once in 2 seconds, then the timeout may be 0 to 2
229 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
230 SilcClientEntry client = (SilcClientEntry)sock->user_data;
231 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
237 if (client->last_command && (time(NULL) - client->last_command) < 2) {
238 client->fast_command++;
241 if (client->fast_command - 2 <= 0)
242 client->fast_command = 0;
244 client->fast_command -= 2;
248 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
249 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
250 silc_schedule_task_add(server->schedule, sock->sock,
251 silc_server_command_process_timeout, timeout,
252 (client->fast_command < 3 ? 0 :
253 2 - (time(NULL) - client->last_command)),
254 (client->fast_command < 3 ? 200000 : 0),
255 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
257 silc_schedule_task_add(server->schedule, sock->sock,
258 silc_server_command_process_timeout, timeout,
259 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
263 /* Execute for server */
265 if (!(cmd->flags & SILC_CF_REG))
267 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
270 silc_server_command_free(ctx);
273 /* Allocate Command Context */
275 SilcServerCommandContext silc_server_command_alloc()
277 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
282 /* Free's the command context allocated before executing the command */
284 void silc_server_command_free(SilcServerCommandContext ctx)
287 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
289 if (ctx->users < 1) {
291 silc_command_payload_free(ctx->payload);
293 silc_packet_context_free(ctx->packet);
295 silc_socket_free(ctx->sock); /* Decrease reference counter */
300 /* Duplicate Command Context by adding reference counter. The context won't
301 be free'd untill it hits zero. */
303 SilcServerCommandContext
304 silc_server_command_dup(SilcServerCommandContext ctx)
307 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
312 /* Add new pending command to be executed when reply to a command has been
313 received. The `reply_cmd' is the command that will call the `callback'
314 with `context' when reply has been received. It can be SILC_COMMAND_NONE
315 to match any command with the `ident'. If `ident' is non-zero
316 the `callback' will be executed when received reply with command
317 identifier `ident'. If there already exists pending command for the
318 specified command, ident, callback and context this function has no
321 bool silc_server_command_pending(SilcServer server,
322 SilcCommand reply_cmd,
324 SilcCommandCb callback,
327 SilcServerCommandPending *reply;
329 /* Check whether identical pending already exists for same command,
330 ident, callback and callback context. If it does then it would be
331 error to register it again. */
332 silc_dlist_start(server->pending_commands);
333 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
334 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
335 reply->callback == callback && reply->context == context)
339 reply = silc_calloc(1, sizeof(*reply));
340 reply->reply_cmd = reply_cmd;
341 reply->ident = ident;
342 reply->context = context;
343 reply->callback = callback;
344 silc_dlist_add(server->pending_commands, reply);
349 /* Deletes pending command by reply command type. */
351 void silc_server_command_pending_del(SilcServer server,
352 SilcCommand reply_cmd,
355 SilcServerCommandPending *r;
357 silc_dlist_start(server->pending_commands);
358 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
359 if (r->reply_cmd == reply_cmd && r->ident == ident) {
360 silc_dlist_del(server->pending_commands, r);
366 /* Checks for pending commands and marks callbacks to be called from
367 the command reply function. Returns TRUE if there were pending command. */
369 SilcServerCommandPendingCallbacks
370 silc_server_command_pending_check(SilcServer server,
371 SilcServerCommandReplyContext ctx,
374 SilcUInt32 *callbacks_count)
376 SilcServerCommandPending *r;
377 SilcServerCommandPendingCallbacks callbacks = NULL;
380 silc_dlist_start(server->pending_commands);
381 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
382 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
383 && r->ident == ident) {
384 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
385 callbacks[i].context = r->context;
386 callbacks[i].callback = r->callback;
392 *callbacks_count = i;
396 /* Sends simple status message as command reply packet */
399 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
406 SILC_LOG_DEBUG(("Sending command status %d", status));
409 silc_command_reply_payload_encode_va(command, status, error,
410 silc_command_get_ident(cmd->payload),
412 silc_server_packet_send(cmd->server, cmd->sock,
413 SILC_PACKET_COMMAND_REPLY, 0,
414 buffer->data, buffer->len, FALSE);
415 silc_buffer_free(buffer);
418 /* Sends command status reply with one extra argument. The argument
419 type must be sent as argument. */
422 silc_server_command_send_status_data(SilcServerCommandContext cmd,
427 const unsigned char *arg,
432 SILC_LOG_DEBUG(("Sending command status %d", status));
435 silc_command_reply_payload_encode_va(command, status, 0,
436 silc_command_get_ident(cmd->payload),
437 1, arg_type, arg, arg_len);
438 silc_server_packet_send(cmd->server, cmd->sock,
439 SILC_PACKET_COMMAND_REPLY, 0,
440 buffer->data, buffer->len, FALSE);
441 silc_buffer_free(buffer);
444 /* This function can be called to check whether in the command reply
445 an error occurred. This function has no effect if this is called
446 when the command function was not called as pending command callback.
447 This returns TRUE if error had occurred. */
450 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
451 SilcServerCommandReplyContext cmdr,
454 if (!cmd->pending || !cmdr)
457 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
460 /* Send the same command reply payload */
461 silc_command_set_ident(cmdr->payload,
462 silc_command_get_ident(cmd->payload));
463 buffer = silc_command_payload_encode_payload(cmdr->payload);
464 silc_server_packet_send(cmd->server, cmd->sock,
465 SILC_PACKET_COMMAND_REPLY, 0,
466 buffer->data, buffer->len, FALSE);
467 silc_buffer_free(buffer);
474 /******************************************************************************
478 ******************************************************************************/
487 #define ADD_ERROR(errptr, errptr_count, _id, _id_type, _index, _status) \
489 errptr = silc_realloc(errptr, sizeof(*errptr) * (errptr_count + 1)); \
492 errptr[errptr_count].id = _id; \
493 errptr[errptr_count].id_type = _id_type; \
494 errptr[errptr_count].index = _index; \
495 errptr[errptr_count].error = _status; \
500 silc_server_command_whois_parse(SilcServerCommandContext cmd,
501 SilcClientID ***client_id,
502 SilcUInt32 *client_id_count,
506 ResolveError *error_client,
507 SilcUInt32 *error_client_count)
511 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
515 /* If client ID is in the command it must be used instead of nickname */
516 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
518 /* No ID, get the nickname@server string and parse it. */
519 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
521 silc_parse_userfqdn(tmp, nickname, server_name);
523 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
524 SILC_STATUS_ERR_BAD_NICKNAME, 0);
528 /* Command includes ID, we must use that. Take all ID's from the
530 for (k = 0, i = 0; i < argc; i++) {
531 tmp = silc_argument_get_arg_type(cmd->args, i + 4, &len);
534 id = silc_id_payload_parse_id(tmp, len, NULL);
536 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
537 (*client_id_count + 1));
538 (*client_id)[k] = id;
539 (*client_id_count)++;
542 ADD_ERROR((*error_client), (*error_client_count), NULL, 0, i + 4,
543 SILC_STATUS_ERR_BAD_CLIENT_ID);
548 /* Get the max count of reply messages allowed */
549 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
551 SILC_GET32_MSB(*count, tmp);
558 /* Resolve context used by both WHOIS and IDENTIFY commands */
560 SilcServerEntry router;
562 unsigned char **res_argv;
563 SilcUInt32 *res_argv_lens;
564 SilcUInt32 *res_argv_types;
566 } *SilcServerResolveContext;
569 silc_server_command_whois_check(SilcServerCommandContext cmd,
570 SilcClientEntry *clients,
571 SilcUInt32 clients_count)
573 SilcServer server = cmd->server;
574 SilcClientEntry entry;
575 SilcServerResolveContext resolve = NULL, r = NULL;
576 SilcUInt32 resolve_count = 0;
580 SILC_LOG_DEBUG(("Start"));
582 for (i = 0; i < clients_count; i++) {
587 if ((entry->nickname && entry->username && entry->userinfo) ||
588 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
592 /* If we are normal server, and we've not resolved this client from
593 router and it is global client, we'll check whether it is on some
594 channel. If not then we cannot be sure about its validity, and
595 we'll resolve it from router. */
596 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
597 entry->connection || silc_hash_table_count(entry->channels))
601 /* We need to resolve this entry since it is not complete */
603 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
604 /* The entry is being resolved (and we are not the resolver) so attach
605 to the command reply and we're done with this one. */
606 silc_server_command_pending(server, SILC_COMMAND_NONE,
607 entry->resolve_cmd_ident,
608 silc_server_command_whois,
609 silc_server_command_dup(cmd));
612 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
613 /* We've resolved this and it still is not ready. We'll return
614 and are that this will be handled again after it is resolved. */
615 for (i = 0; i < resolve_count; i++) {
616 for (k = 0; k < r->res_argc; k++)
617 silc_free(r->res_argv[k]);
618 silc_free(r->res_argv);
619 silc_free(r->res_argv_lens);
620 silc_free(r->res_argv_types);
625 /* We'll resolve this client */
629 for (k = 0; k < resolve_count; k++) {
630 if (resolve[k].router == entry->router) {
637 resolve = silc_realloc(resolve, sizeof(*resolve) *
638 (resolve_count + 1));
639 r = &resolve[resolve_count];
640 memset(r, 0, sizeof(*r));
641 r->router = entry->router;
642 r->ident = ++server->cmd_ident;
646 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
648 r->res_argv_lens = silc_realloc(r->res_argv_lens,
649 sizeof(*r->res_argv_lens) *
651 r->res_argv_types = silc_realloc(r->res_argv_types,
652 sizeof(*r->res_argv_types) *
654 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
655 r->res_argv[r->res_argc] = silc_calloc(idp->len,
656 sizeof(**r->res_argv));
657 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
658 r->res_argv_lens[r->res_argc] = idp->len;
659 r->res_argv_types[r->res_argc] = r->res_argc + 4;
661 silc_buffer_free(idp);
663 entry->resolve_cmd_ident = r->ident;
664 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
665 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
670 /* Do the resolving */
671 for (i = 0; i < resolve_count; i++) {
676 /* Send WHOIS request. We send WHOIS since we're doing the requesting
677 now anyway so make it a good one. */
678 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
679 r->res_argc, r->res_argv,
683 silc_server_packet_send(server, r->router->connection,
684 SILC_PACKET_COMMAND, cmd->packet->flags,
685 res_cmd->data, res_cmd->len, FALSE);
687 /* Reprocess this packet after received reply */
688 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
690 silc_server_command_whois,
691 silc_server_command_dup(cmd));
694 silc_buffer_free(res_cmd);
695 for (k = 0; k < r->res_argc; k++)
696 silc_free(r->res_argv[k]);
697 silc_free(r->res_argv);
698 silc_free(r->res_argv_lens);
699 silc_free(r->res_argv_types);
708 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
709 SilcClientEntry *clients,
710 SilcUInt32 clients_count,
712 SilcUInt32 errors_count,
713 int count, const char *nickname,
714 SilcClientID **client_ids)
716 SilcServer server = cmd->server;
718 int i, k, valid_count = clients_count;
720 SilcBuffer packet, idp, channels, umode_list = NULL;
721 SilcClientEntry entry;
723 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
724 char nh[256], uh[256];
725 unsigned char idle[4], mode[4];
726 unsigned char *fingerprint;
727 SilcSocketConnection hsock;
730 /* Process only valid clients and ignore those that are not registered.
731 This is checked with nickname only because when resolved client IDs
732 we check that they are registered earlier. */
734 for (i = 0; i < clients_count; i++)
735 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
741 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
742 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
743 3, nickname, strlen(nickname));
748 /* Start processing found clients. */
749 status = SILC_STATUS_OK;
751 status = SILC_STATUS_LIST_START;
753 for (i = 0, k = 0; i < clients_count; i++) {
759 status = SILC_STATUS_LIST_ITEM;
760 if (valid_count > 1 && k == valid_count - 1 && !errors_count)
761 status = SILC_STATUS_LIST_END;
762 if (count && k - 1 == count)
763 status = SILC_STATUS_LIST_END;
765 /* Send WHOIS reply */
766 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
767 tmp = silc_argument_get_first_arg(cmd->args, NULL);
769 memset(uh, 0, sizeof(uh));
770 memset(nh, 0, sizeof(nh));
771 memset(idle, 0, sizeof(idle));
773 strncat(nh, entry->nickname, strlen(entry->nickname));
774 if (!strchr(entry->nickname, '@')) {
776 if (entry->servername) {
777 strncat(nh, entry->servername, strlen(entry->servername));
779 len = entry->router ? strlen(entry->router->server_name) :
780 strlen(server->server_name);
781 strncat(nh, entry->router ? entry->router->server_name :
782 server->server_name, len);
786 strncat(uh, entry->username, strlen(entry->username));
787 if (!strchr(entry->username, '@') && entry->connection) {
789 hsock = (SilcSocketConnection)entry->connection;
790 len = strlen(hsock->hostname);
791 strncat(uh, hsock->hostname, len);
794 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
795 channels = silc_server_get_client_channel_list(server, entry, FALSE,
798 channels = silc_server_get_client_channel_list(server, entry, TRUE,
801 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
802 fingerprint = entry->data.fingerprint;
806 SILC_PUT32_MSB(entry->mode, mode);
807 if (entry->connection)
808 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
811 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
813 2, idp->data, idp->len,
817 strlen(entry->userinfo),
818 6, channels ? channels->data : NULL,
819 channels ? channels->len : 0,
823 fingerprint ? 20 : 0,
824 10, umode_list ? umode_list->data :
825 NULL, umode_list ? umode_list->len :
828 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
829 0, packet->data, packet->len, FALSE);
831 silc_buffer_free(packet);
832 silc_buffer_free(idp);
834 silc_buffer_free(channels);
836 silc_buffer_free(umode_list);
840 if (status == SILC_STATUS_LIST_END)
845 /* Send error replies */
846 if (status == SILC_STATUS_OK && errors_count > 1)
847 status = SILC_STATUS_LIST_START;
850 for (i = 0, k = 0; i < errors_count; i++) {
852 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
856 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
860 status = SILC_STATUS_LIST_ITEM;
861 if (errors_count > 1 && k == errors_count - 1)
862 status = SILC_STATUS_LIST_END;
863 if (count && k - 1 == count)
864 status = SILC_STATUS_LIST_END;
867 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
868 (status == SILC_STATUS_OK ?
869 errors[i].error : status),
870 (status == SILC_STATUS_OK ?
871 0 : errors[i].error),
873 silc_buffer_free(idp);
876 if (status == SILC_STATUS_LIST_END)
883 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
885 SilcServer server = cmd->server;
887 SilcUInt16 old_ident;
889 old_ident = silc_command_get_ident(cmd->payload);
890 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
891 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
893 /* Send WHOIS command to our router */
894 silc_server_packet_send(server, (SilcSocketConnection)
895 server->router->connection,
896 SILC_PACKET_COMMAND, cmd->packet->flags,
897 tmpbuf->data, tmpbuf->len, TRUE);
899 /* Reprocess this packet after received reply from router */
900 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
901 silc_command_get_ident(cmd->payload),
902 silc_server_command_whois,
903 silc_server_command_dup(cmd));
905 silc_command_set_ident(cmd->payload, old_ident);
906 silc_buffer_free(tmpbuf);
910 silc_server_command_whois_process(SilcServerCommandContext cmd)
912 SilcServer server = cmd->server;
913 char *nick = NULL, *server_name = NULL;
915 SilcClientEntry *clients = NULL, entry;
916 SilcClientID **client_id = NULL;
917 SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
918 ResolveError error_client = NULL;
920 bool check_global = FALSE;
922 /* Parse the whois request */
923 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
924 &nick, &server_name, &count,
925 &error_client, &error_client_count))
928 /* Send the WHOIS request to the router only if it included nickname.
929 Since nicknames can be expanded into many clients we need to send it
930 to router. If the WHOIS included only client ID's we will check them
931 first locally since we just might have them. */
932 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
933 server->server_type == SILC_SERVER && !cmd->pending &&
934 !server->standalone) {
935 silc_server_command_whois_send_router(cmd);
940 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
942 else if (server->server_type != SILC_SERVER)
945 /* Get all clients matching that ID or nickname from local list */
946 if (client_id_count) {
947 /* Check all Client ID's received in the command packet */
948 for (i = 0; i < client_id_count; i++) {
949 entry = silc_idlist_find_client_by_id(server->local_list,
950 client_id[i], TRUE, NULL);
951 if (!entry && check_global)
952 entry = silc_idlist_find_client_by_id(server->global_list,
953 client_id[i], TRUE, NULL);
955 clients = silc_realloc(clients, sizeof(*clients) *
956 (clients_count + 1));
957 clients[clients_count++] = entry;
959 /* If we are normal server and did not send the request first to router
960 do it now, since we do not have the Client ID information. */
961 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
962 server->server_type == SILC_SERVER && !cmd->pending &&
963 !server->standalone) {
964 silc_server_command_whois_send_router(cmd);
969 ADD_ERROR(error_client, error_client_count, client_id[i],
970 SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
974 /* Find by nickname */
975 if (!silc_idlist_get_clients_by_hash(server->local_list,
976 nick, server->md5hash,
977 &clients, &clients_count))
978 silc_idlist_get_clients_by_nickname(server->local_list,
980 &clients, &clients_count);
982 if (!silc_idlist_get_clients_by_hash(server->global_list,
983 nick, server->md5hash,
984 &clients, &clients_count))
985 silc_idlist_get_clients_by_nickname(server->global_list,
987 &clients, &clients_count);
991 if (!clients && (client_id_count || nick)) {
992 /* If we are normal server and did not send the request first to router
993 do it now, since we do not have the information. */
994 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
995 server->server_type == SILC_SERVER && !cmd->pending &&
996 !server->standalone) {
997 silc_server_command_whois_send_router(cmd);
1002 /* Such client(s) really does not exist in the SILC network. */
1003 if (!client_id_count)
1004 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1005 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1006 3, nick, strlen(nick));
1008 silc_server_command_whois_send_reply(cmd, NULL, 0,
1009 error_client, error_client_count,
1014 /* Router always finds the client entry if it exists in the SILC network.
1015 However, it might be incomplete entry and does not include all the
1016 mandatory fields that WHOIS command reply requires. Check for these and
1017 make query from the server who owns the client if some fields are
1019 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
1024 /* Send the command reply */
1025 silc_server_command_whois_send_reply(cmd, clients, clients_count,
1026 error_client, error_client_count,
1027 count, nick, client_id);
1030 if (client_id_count) {
1031 for (i = 0; i < client_id_count; i++)
1032 silc_free(client_id[i]);
1033 silc_free(client_id);
1036 silc_free(error_client);
1038 silc_free(server_name);
1043 /* Server side of command WHOIS. Processes user's query and sends found
1044 results as command replies back to the client. */
1046 SILC_SERVER_CMD_FUNC(whois)
1048 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1051 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1053 ret = silc_server_command_whois_process(cmd);
1054 silc_server_command_free(cmd);
1057 /******************************************************************************
1061 ******************************************************************************/
1064 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1072 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1074 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1075 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1080 /* Get the nickname@server string and parse it. */
1081 silc_parse_userfqdn(tmp, nickname, server_name);
1083 /* Get the max count of reply messages allowed */
1084 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1086 SILC_GET32_MSB(*count, tmp);
1094 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1095 SilcClientEntry *clients,
1096 SilcUInt32 clients_count)
1098 SilcServer server = cmd->server;
1100 SilcClientEntry entry;
1102 for (i = 0; i < clients_count; i++) {
1105 if (!entry->nickname || !entry->username) {
1107 SilcUInt16 old_ident;
1112 old_ident = silc_command_get_ident(cmd->payload);
1113 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1114 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1116 /* Send WHOWAS command */
1117 silc_server_packet_send(server, entry->router->connection,
1118 SILC_PACKET_COMMAND, cmd->packet->flags,
1119 tmpbuf->data, tmpbuf->len, TRUE);
1121 /* Reprocess this packet after received reply */
1122 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1123 silc_command_get_ident(cmd->payload),
1124 silc_server_command_whowas,
1125 silc_server_command_dup(cmd));
1126 cmd->pending = TRUE;
1127 silc_command_set_ident(cmd->payload, old_ident);
1129 silc_buffer_free(tmpbuf);
1138 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1139 SilcClientEntry *clients,
1140 SilcUInt32 clients_count)
1142 SilcServer server = cmd->server;
1144 int i, k, count = 0, len;
1145 SilcBuffer packet, idp;
1146 SilcClientEntry entry = NULL;
1148 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1149 char nh[256], uh[256];
1152 status = SILC_STATUS_OK;
1154 /* Process only entries that are not registered anymore. */
1156 for (i = 0; i < clients_count; i++) {
1157 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1164 /* No valid entries found at all, just send error */
1165 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1166 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1167 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1168 3, tmp, tmp ? strlen(tmp) : 0);
1172 if (valid_count > 1)
1173 status = SILC_STATUS_LIST_START;
1175 for (i = 0, k = 0; i < clients_count; i++) {
1181 status = SILC_STATUS_LIST_ITEM;
1182 if (valid_count > 1 && k == valid_count - 1)
1183 status = SILC_STATUS_LIST_END;
1184 if (count && k - 1 == count)
1185 status = SILC_STATUS_LIST_END;
1187 /* Send WHOWAS reply */
1188 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1189 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1190 memset(uh, 0, sizeof(uh));
1191 memset(nh, 0, sizeof(nh));
1193 strncat(nh, entry->nickname, strlen(entry->nickname));
1194 if (!strchr(entry->nickname, '@')) {
1195 strncat(nh, "@", 1);
1196 if (entry->servername) {
1197 strncat(nh, entry->servername, strlen(entry->servername));
1199 len = entry->router ? strlen(entry->router->server_name) :
1200 strlen(server->server_name);
1201 strncat(nh, entry->router ? entry->router->server_name :
1202 server->server_name, len);
1206 strncat(uh, entry->username, strlen(entry->username));
1207 if (!strchr(entry->username, '@')) {
1208 strncat(uh, "@", 1);
1209 strcat(uh, "*private*");
1213 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1214 status, 0, ident, 4,
1215 2, idp->data, idp->len,
1220 strlen(entry->userinfo) : 0);
1221 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1222 0, packet->data, packet->len, FALSE);
1224 silc_buffer_free(packet);
1225 silc_buffer_free(idp);
1227 if (status == SILC_STATUS_LIST_END)
1234 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1236 SilcServer server = cmd->server;
1237 char *nick = NULL, *server_name = NULL;
1239 SilcClientEntry *clients = NULL;
1240 SilcUInt32 clients_count = 0;
1242 bool check_global = FALSE;
1244 /* Protocol dictates that we must always send the received WHOWAS request
1245 to our router if we are normal server, so let's do it now unless we
1246 are standalone. We will not send any replies to the client until we
1247 have received reply from the router. */
1248 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1249 server->server_type == SILC_SERVER && !cmd->pending &&
1250 !server->standalone) {
1252 SilcUInt16 old_ident;
1254 old_ident = silc_command_get_ident(cmd->payload);
1255 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1256 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1258 /* Send WHOWAS command to our router */
1259 silc_server_packet_send(server, (SilcSocketConnection)
1260 server->router->connection,
1261 SILC_PACKET_COMMAND, cmd->packet->flags,
1262 tmpbuf->data, tmpbuf->len, TRUE);
1264 /* Reprocess this packet after received reply from router */
1265 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1266 silc_command_get_ident(cmd->payload),
1267 silc_server_command_whowas,
1268 silc_server_command_dup(cmd));
1269 cmd->pending = TRUE;
1270 silc_command_set_ident(cmd->payload, old_ident);
1272 silc_buffer_free(tmpbuf);
1277 /* We are ready to process the command request. Let's search for the
1278 requested client and send reply to the requesting client. */
1280 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1281 check_global = TRUE;
1282 else if (server->server_type != SILC_SERVER)
1283 check_global = TRUE;
1285 /* Parse the whowas request */
1286 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1289 /* Get all clients matching that nickname from local list */
1290 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1292 &clients, &clients_count))
1293 silc_idlist_get_clients_by_hash(server->local_list,
1294 nick, server->md5hash,
1295 &clients, &clients_count);
1297 /* Check global list as well */
1299 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1301 &clients, &clients_count))
1302 silc_idlist_get_clients_by_hash(server->global_list,
1303 nick, server->md5hash,
1304 &clients, &clients_count);
1308 /* Such a client really does not exist in the SILC network. */
1309 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1310 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1311 3, nick, strlen(nick));
1315 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1320 /* Send the command reply to the client */
1321 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1326 silc_free(server_name);
1330 /* Server side of command WHOWAS. */
1332 SILC_SERVER_CMD_FUNC(whowas)
1334 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1337 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1339 ret = silc_server_command_whowas_process(cmd);
1340 silc_server_command_free(cmd);
1343 /******************************************************************************
1347 ******************************************************************************/
1350 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1352 SilcServer server = cmd->server;
1354 SilcUInt16 old_ident;
1356 old_ident = silc_command_get_ident(cmd->payload);
1357 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1358 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1360 /* Send IDENTIFY command to our router */
1361 silc_server_packet_send(server, (SilcSocketConnection)
1362 server->router->connection,
1363 SILC_PACKET_COMMAND, cmd->packet->flags,
1364 tmpbuf->data, tmpbuf->len, TRUE);
1366 /* Reprocess this packet after received reply from router */
1367 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1368 silc_command_get_ident(cmd->payload),
1369 silc_server_command_identify,
1370 silc_server_command_dup(cmd));
1371 cmd->pending = TRUE;
1372 silc_command_set_ident(cmd->payload, old_ident);
1373 silc_buffer_free(tmpbuf);
1377 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1378 SilcClientEntry **clients,
1379 SilcUInt32 *clients_count,
1380 SilcServerEntry **servers,
1381 SilcUInt32 *servers_count,
1382 SilcChannelEntry **channels,
1383 SilcUInt32 *channels_count,
1385 ResolveError *error_id,
1386 SilcUInt32 *error_id_count)
1388 SilcServer server = cmd->server;
1391 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1393 bool check_global = FALSE;
1397 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1398 check_global = TRUE;
1399 else if (server->server_type != SILC_SERVER)
1400 check_global = TRUE;
1402 /* If ID Payload is in the command it must be used instead of names */
1403 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1405 /* No ID, get the names. */
1407 /* If we are normal server and have not resolved information from
1408 router yet, do so now. */
1409 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1410 server->server_type == SILC_SERVER && !cmd->pending &&
1411 !server->standalone) {
1412 silc_server_command_identify_send_router(cmd);
1416 /* Try to get nickname@server. */
1417 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1420 char *nick_server = NULL;
1422 silc_parse_userfqdn(tmp, &nick, &nick_server);
1424 if (!silc_idlist_get_clients_by_hash(server->local_list,
1425 nick, server->md5hash,
1426 clients, clients_count))
1427 silc_idlist_get_clients_by_nickname(server->local_list,
1429 clients, clients_count);
1431 if (!silc_idlist_get_clients_by_hash(server->global_list,
1432 nick, server->md5hash,
1433 clients, clients_count))
1434 silc_idlist_get_clients_by_nickname(server->global_list,
1436 clients, clients_count);
1440 silc_free(nick_server);
1443 /* the nickname does not exist, send error reply */
1444 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1445 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1446 3, tmp, strlen(tmp));
1451 /* Try to get server name */
1452 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1454 entry = silc_idlist_find_server_by_name(server->local_list,
1456 if (!entry && check_global)
1457 entry = silc_idlist_find_server_by_name(server->global_list,
1460 *servers = silc_realloc(*servers, sizeof(**servers) *
1461 (*servers_count + 1));
1462 (*servers)[(*servers_count)++] = entry;
1466 /* the server does not exist, send error reply */
1467 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1468 SILC_STATUS_ERR_NO_SUCH_SERVER,
1469 0, 3, tmp, strlen(tmp));
1474 /* Try to get channel name */
1475 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1477 entry = silc_idlist_find_channel_by_name(server->local_list,
1479 if (!entry && check_global)
1480 entry = silc_idlist_find_channel_by_name(server->global_list,
1483 *channels = silc_realloc(*channels, sizeof(**channels) *
1484 (*channels_count + 1));
1485 (*channels)[(*channels_count)++] = entry;
1489 /* The channel does not exist, send error reply */
1490 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1491 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1492 0, 3, tmp, strlen(tmp));
1497 if (!(*clients) && !(*servers) && !(*channels)) {
1498 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1499 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1504 /* Command includes ID, we must use that. Also check whether the command
1505 has more than one ID set - take them all. */
1507 /* Take all ID's from the command packet */
1508 for (i = 0; i < argc; i++) {
1511 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1515 idp = silc_id_payload_parse(tmp, len);
1517 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1518 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1520 id = silc_id_payload_get_id(idp);
1521 switch (silc_id_payload_get_type(idp)) {
1523 case SILC_ID_CLIENT:
1524 entry = silc_idlist_find_client_by_id(server->local_list,
1526 if (!entry && check_global)
1527 entry = silc_idlist_find_client_by_id(server->global_list,
1530 *clients = silc_realloc(*clients, sizeof(**clients) *
1531 (*clients_count + 1));
1532 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1534 /* If we are normal server and have not resolved information from
1535 router yet, do so now. */
1536 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1537 server->server_type == SILC_SERVER && !cmd->pending &&
1538 !server->standalone) {
1539 silc_server_command_identify_send_router(cmd);
1540 silc_free(*clients);
1541 silc_free(*servers);
1542 silc_free(*channels);
1543 silc_free(*error_id);
1547 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1548 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1553 case SILC_ID_SERVER:
1554 entry = silc_idlist_find_server_by_id(server->local_list,
1556 if (!entry && check_global)
1557 entry = silc_idlist_find_server_by_id(server->global_list,
1560 *servers = silc_realloc(*servers, sizeof(**servers) *
1561 (*servers_count + 1));
1562 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1564 /* If we are normal server and have not resolved information from
1565 router yet, do so now. */
1566 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1567 server->server_type == SILC_SERVER && !cmd->pending &&
1568 !server->standalone) {
1569 silc_server_command_identify_send_router(cmd);
1570 silc_free(*clients);
1571 silc_free(*servers);
1572 silc_free(*channels);
1573 silc_free(*error_id);
1577 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1578 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
1582 case SILC_ID_CHANNEL:
1583 entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
1584 if (!entry && check_global)
1585 entry = silc_idlist_find_channel_by_id(server->global_list, id,
1588 *channels = silc_realloc(*channels, sizeof(**channels) *
1589 (*channels_count + 1));
1590 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1592 /* If we are normal server and have not resolved information from
1593 router yet, do so now. */
1594 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1595 server->server_type == SILC_SERVER && !cmd->pending &&
1596 !server->standalone) {
1597 silc_server_command_identify_send_router(cmd);
1598 silc_free(*clients);
1599 silc_free(*servers);
1600 silc_free(*channels);
1601 silc_free(*error_id);
1605 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1606 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
1615 /* Get the max count of reply messages allowed */
1616 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1618 SILC_GET32_MSB(*count, tmp);
1625 /* Checks that all mandatory fields in client entry are present. If not
1626 then send WHOIS request to the server who owns the client. We use
1627 WHOIS because we want to get as much information as possible at once. */
1630 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1631 SilcClientEntry *clients,
1632 SilcUInt32 clients_count)
1634 SilcServer server = cmd->server;
1635 SilcClientEntry entry;
1636 SilcServerResolveContext resolve = NULL, r = NULL;
1637 SilcUInt32 resolve_count = 0;
1641 for (i = 0; i < clients_count; i++) {
1646 if (entry->nickname ||
1647 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1651 /* If we are normal server, and we've not resolved this client from
1652 router and it is global client, we'll check whether it is on some
1653 channel. If not then we cannot be sure about its validity, and
1654 we'll resolve it from router. */
1655 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1656 entry->connection || silc_hash_table_count(entry->channels))
1660 /* We need to resolve this entry since it is not complete */
1662 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1663 /* The entry is being resolved (and we are not the resolver) so attach
1664 to the command reply and we're done with this one. */
1665 silc_server_command_pending(server, SILC_COMMAND_NONE,
1666 entry->resolve_cmd_ident,
1667 silc_server_command_identify,
1668 silc_server_command_dup(cmd));
1671 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1672 /* We've resolved this and it still is not ready. We'll return
1673 and are that this will be handled again after it is resolved. */
1674 for (i = 0; i < resolve_count; i++) {
1675 for (k = 0; k < r->res_argc; k++)
1676 silc_free(r->res_argv[k]);
1677 silc_free(r->res_argv);
1678 silc_free(r->res_argv_lens);
1679 silc_free(r->res_argv_types);
1684 /* We'll resolve this client */
1688 for (k = 0; k < resolve_count; k++) {
1689 if (resolve[k].router == entry->router) {
1696 resolve = silc_realloc(resolve, sizeof(*resolve) *
1697 (resolve_count + 1));
1698 r = &resolve[resolve_count];
1699 memset(r, 0, sizeof(*r));
1700 r->router = entry->router;
1701 r->ident = ++server->cmd_ident;
1705 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1707 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1708 sizeof(*r->res_argv_lens) *
1710 r->res_argv_types = silc_realloc(r->res_argv_types,
1711 sizeof(*r->res_argv_types) *
1713 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1714 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1715 sizeof(**r->res_argv));
1716 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1717 r->res_argv_lens[r->res_argc] = idp->len;
1718 r->res_argv_types[r->res_argc] = r->res_argc + 4;
1720 silc_buffer_free(idp);
1722 entry->resolve_cmd_ident = r->ident;
1723 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1724 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1729 /* Do the resolving */
1730 for (i = 0; i < resolve_count; i++) {
1735 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1736 now anyway so make it a good one. */
1737 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1738 r->res_argc, r->res_argv,
1742 silc_server_packet_send(server, r->router->connection,
1743 SILC_PACKET_COMMAND, cmd->packet->flags,
1744 res_cmd->data, res_cmd->len, FALSE);
1746 /* Reprocess this packet after received reply */
1747 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1749 silc_server_command_identify,
1750 silc_server_command_dup(cmd));
1751 cmd->pending = TRUE;
1753 silc_buffer_free(res_cmd);
1754 for (k = 0; k < r->res_argc; k++)
1755 silc_free(r->res_argv[k]);
1756 silc_free(r->res_argv);
1757 silc_free(r->res_argv_lens);
1758 silc_free(r->res_argv_types);
1767 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1768 SilcClientEntry *clients,
1769 SilcUInt32 clients_count,
1770 SilcServerEntry *servers,
1771 SilcUInt32 servers_count,
1772 SilcChannelEntry *channels,
1773 SilcUInt32 channels_count,
1774 ResolveError errors,
1775 SilcUInt32 errors_count,
1778 SilcServer server = cmd->server;
1779 int i, k, valid_count;
1781 SilcBuffer packet, idp;
1783 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1784 char nh[256], uh[256];
1785 SilcSocketConnection hsock;
1788 status = SILC_STATUS_OK;
1791 SilcClientEntry entry;
1792 valid_count = clients_count;
1794 if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
1795 /* Process only valid clients and ignore those that are not registered.
1796 This is checked with nickname only because when resolved client IDs
1797 we check that they are registered earlier. */
1799 for (i = 0; i < clients_count; i++) {
1800 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1807 /* No valid entries found at all, just send error */
1808 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1809 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1810 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1811 3, tmp, tmp ? strlen(tmp) : 0);
1816 /* Process all valid client entries and send command replies */
1818 if (valid_count > 1)
1819 status = SILC_STATUS_LIST_START;
1821 for (i = 0, k = 0; i < clients_count; i++) {
1827 status = SILC_STATUS_LIST_ITEM;
1828 if (valid_count > 1 && k == valid_count - 1
1829 && !servers_count && !channels_count && !errors_count)
1830 status = SILC_STATUS_LIST_END;
1831 if (count && k - 1 == count)
1832 status = SILC_STATUS_LIST_END;
1834 /* Send IDENTIFY reply */
1836 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1837 memset(uh, 0, sizeof(uh));
1838 memset(nh, 0, sizeof(nh));
1839 strncat(nh, entry->nickname, strlen(entry->nickname));
1840 if (!strchr(entry->nickname, '@')) {
1841 strncat(nh, "@", 1);
1842 if (entry->servername) {
1843 strncat(nh, entry->servername, strlen(entry->servername));
1845 len = entry->router ? strlen(entry->router->server_name) :
1846 strlen(server->server_name);
1847 strncat(nh, entry->router ? entry->router->server_name :
1848 server->server_name, len);
1852 if (!entry->username) {
1853 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1854 status, 0, ident, 2,
1855 2, idp->data, idp->len,
1858 strncat(uh, entry->username, strlen(entry->username));
1859 if (!strchr(entry->username, '@') && entry->connection) {
1860 strncat(uh, "@", 1);
1861 hsock = (SilcSocketConnection)entry->connection;
1862 len = strlen(hsock->hostname);
1863 strncat(uh, hsock->hostname, len);
1866 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1867 status, 0, ident, 3,
1868 2, idp->data, idp->len,
1873 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1874 0, packet->data, packet->len, FALSE);
1876 silc_buffer_free(packet);
1877 silc_buffer_free(idp);
1879 if (status == SILC_STATUS_LIST_END)
1886 SilcServerEntry entry;
1888 if (status == SILC_STATUS_OK && servers_count > 1)
1889 status = SILC_STATUS_LIST_START;
1891 for (i = 0, k = 0; i < servers_count; i++) {
1895 status = SILC_STATUS_LIST_ITEM;
1896 if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
1898 status = SILC_STATUS_LIST_END;
1899 if (count && k - 1 == count)
1900 status = SILC_STATUS_LIST_END;
1902 /* Send IDENTIFY reply */
1903 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1905 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1906 status, 0, ident, 2,
1907 2, idp->data, idp->len,
1908 3, entry->server_name,
1909 entry->server_name ?
1910 strlen(entry->server_name) : 0);
1911 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1912 0, packet->data, packet->len, FALSE);
1914 silc_buffer_free(packet);
1915 silc_buffer_free(idp);
1917 if (status == SILC_STATUS_LIST_END)
1924 SilcChannelEntry entry;
1926 if (status == SILC_STATUS_OK && channels_count > 1)
1927 status = SILC_STATUS_LIST_START;
1929 for (i = 0, k = 0; i < channels_count; i++) {
1930 entry = channels[i];
1933 status = SILC_STATUS_LIST_ITEM;
1934 if (channels_count > 1 && k == channels_count - 1 && !errors_count)
1935 status = SILC_STATUS_LIST_END;
1936 if (count && k - 1 == count)
1937 status = SILC_STATUS_LIST_END;
1939 /* Send IDENTIFY reply */
1940 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1942 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1943 status, 0, ident, 2,
1944 2, idp->data, idp->len,
1945 3, entry->channel_name,
1946 entry->channel_name ?
1947 strlen(entry->channel_name): 0);
1948 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1949 0, packet->data, packet->len, FALSE);
1951 silc_buffer_free(packet);
1952 silc_buffer_free(idp);
1954 if (status == SILC_STATUS_LIST_END)
1960 /* Send error replies */
1962 if (status == SILC_STATUS_OK && errors_count > 1)
1963 status = SILC_STATUS_LIST_START;
1966 for (i = 0, k = 0; i < errors_count; i++) {
1968 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
1972 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
1976 status = SILC_STATUS_LIST_ITEM;
1977 if (errors_count > 1 && k == errors_count - 1)
1978 status = SILC_STATUS_LIST_END;
1979 if (count && k - 1 == count)
1980 status = SILC_STATUS_LIST_END;
1983 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1984 (status == SILC_STATUS_OK ?
1985 errors[i].error : status),
1986 (status == SILC_STATUS_OK ?
1987 0 : errors[i].error),
1989 silc_buffer_free(idp);
1992 if (status == SILC_STATUS_LIST_END)
2000 silc_server_command_identify_process(SilcServerCommandContext cmd)
2002 SilcUInt32 count = 0;
2004 SilcClientEntry *clients = NULL;
2005 SilcServerEntry *servers = NULL;
2006 SilcChannelEntry *channels = NULL;
2007 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
2008 SilcUInt32 errors_count = 0;
2009 ResolveError errors = NULL;
2011 /* Parse the IDENTIFY request */
2012 ret = silc_server_command_identify_parse(cmd,
2013 &clients, &clients_count,
2014 &servers, &servers_count,
2015 &channels, &channels_count,
2016 &count, &errors, &errors_count);
2021 /* Check that all mandatory fields are present and request those data
2022 from the server who owns the client if necessary. */
2023 if (!silc_server_command_identify_check_client(cmd, clients,
2029 /* Send the command reply to the client */
2030 silc_server_command_identify_send_reply(cmd,
2031 clients, clients_count,
2032 servers, servers_count,
2033 channels, channels_count,
2034 errors, errors_count,
2040 silc_free(channels);
2045 SILC_SERVER_CMD_FUNC(identify)
2047 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2050 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2052 ret = silc_server_command_identify_process(cmd);
2053 silc_server_command_free(cmd);
2056 /* Server side of command NICK. Sets nickname for user. Setting
2057 nickname causes generation of a new client ID for the client. The
2058 new client ID is sent to the client after changing the nickname. */
2060 SILC_SERVER_CMD_FUNC(nick)
2062 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2063 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2064 SilcServer server = cmd->server;
2065 SilcBuffer packet, nidp, oidp = NULL;
2066 SilcClientID *new_id;
2067 SilcUInt32 nick_len;
2069 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2072 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2075 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2077 /* Check nickname */
2078 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2081 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2083 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2087 /* Check for same nickname */
2088 if (!strcmp(client->nickname, nick)) {
2089 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2093 /* Create new Client ID */
2094 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2096 cmd->server->md5hash, nick,
2100 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2101 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2104 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2107 /* Send notify about nickname change to our router. We send the new
2108 ID and ask to replace it with the old one. If we are router the
2109 packet is broadcasted. Send NICK_CHANGE notify. */
2110 if (!server->standalone)
2111 silc_server_send_notify_nick_change(server, server->router->connection,
2112 server->server_type == SILC_SERVER ?
2113 FALSE : TRUE, client->id,
2116 /* Check if anyone is watching the old nickname */
2117 if (server->server_type == SILC_ROUTER)
2118 silc_server_check_watcher_list(server, client, nick,
2119 SILC_NOTIFY_TYPE_NICK_CHANGE);
2121 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2123 /* Remove old cache entry */
2124 silc_idcache_del_by_context(server->local_list->clients, client);
2126 silc_free(client->id);
2127 client->id = new_id;
2129 silc_free(client->nickname);
2130 client->nickname = strdup(nick);
2132 /* Update client cache */
2133 silc_idcache_add(server->local_list->clients, client->nickname,
2134 client->id, (void *)client, 0, NULL);
2136 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2138 /* Send NICK_CHANGE notify to the client's channels */
2139 silc_server_send_notify_on_channels(server, NULL, client,
2140 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2141 oidp->data, oidp->len,
2142 nidp->data, nidp->len,
2144 strlen(client->nickname));
2146 /* Check if anyone is watching the new nickname */
2147 if (server->server_type == SILC_ROUTER)
2148 silc_server_check_watcher_list(server, client, NULL,
2149 SILC_NOTIFY_TYPE_NICK_CHANGE);
2152 /* Send the new Client ID as reply command back to client */
2153 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2154 SILC_STATUS_OK, 0, ident, 2,
2155 2, nidp->data, nidp->len,
2156 3, nick, strlen(nick));
2157 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2158 0, packet->data, packet->len, FALSE);
2160 silc_buffer_free(packet);
2161 silc_buffer_free(nidp);
2163 silc_buffer_free(oidp);
2166 silc_server_command_free(cmd);
2169 /* Sends the LIST command reply */
2172 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2173 SilcChannelEntry *lch,
2174 SilcUInt32 lch_count,
2175 SilcChannelEntry *gch,
2176 SilcUInt32 gch_count)
2179 SilcBuffer packet, idp;
2180 SilcChannelEntry entry;
2182 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2184 unsigned char usercount[4];
2186 int valid_lcount = 0, valid_rcount = 0;
2188 for (i = 0; i < lch_count; i++) {
2189 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2194 for (i = 0; i < gch_count; i++) {
2195 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2201 status = SILC_STATUS_OK;
2202 if ((lch_count + gch_count) > 1)
2203 status = SILC_STATUS_LIST_START;
2206 for (i = 0, k = 0; i < lch_count; i++) {
2212 status = SILC_STATUS_LIST_ITEM;
2213 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2214 status = SILC_STATUS_LIST_END;
2216 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2218 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2219 topic = "*private*";
2220 memset(usercount, 0, sizeof(usercount));
2222 topic = entry->topic;
2223 users = silc_hash_table_count(entry->user_list);
2224 SILC_PUT32_MSB(users, usercount);
2227 /* Send the reply */
2229 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2230 status, 0, ident, 4,
2231 2, idp->data, idp->len,
2232 3, entry->channel_name,
2233 strlen(entry->channel_name),
2234 4, topic, topic ? strlen(topic) : 0,
2236 silc_server_packet_send(cmd->server, cmd->sock,
2237 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2238 packet->len, FALSE);
2239 silc_buffer_free(packet);
2240 silc_buffer_free(idp);
2245 for (i = 0, k = 0; i < gch_count; i++) {
2251 status = SILC_STATUS_LIST_ITEM;
2252 if (valid_rcount > 1 && k == valid_rcount - 1)
2253 status = SILC_STATUS_LIST_END;
2255 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2257 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2258 topic = "*private*";
2259 memset(usercount, 0, sizeof(usercount));
2261 topic = entry->topic;
2262 users = entry->user_count;
2263 SILC_PUT32_MSB(users, usercount);
2266 /* Send the reply */
2268 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2269 status, 0, ident, 4,
2270 2, idp->data, idp->len,
2271 3, entry->channel_name,
2272 strlen(entry->channel_name),
2273 4, topic, topic ? strlen(topic) : 0,
2275 silc_server_packet_send(cmd->server, cmd->sock,
2276 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2277 packet->len, FALSE);
2278 silc_buffer_free(packet);
2279 silc_buffer_free(idp);
2284 /* Server side of LIST command. This lists the channel of the requested
2285 server. Secret channels are not listed. */
2287 SILC_SERVER_CMD_FUNC(list)
2289 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2290 SilcServer server = cmd->server;
2291 SilcChannelID *channel_id = NULL;
2294 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2295 SilcUInt32 lch_count = 0, gch_count = 0;
2297 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2299 /* If we are normal server, send the command to router, since we
2300 want to know all channels in the network. */
2301 if (!cmd->pending && server->server_type == SILC_SERVER &&
2302 !server->standalone) {
2304 SilcUInt16 old_ident;
2306 old_ident = silc_command_get_ident(cmd->payload);
2307 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2308 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2309 silc_server_packet_send(server, server->router->connection,
2310 SILC_PACKET_COMMAND, cmd->packet->flags,
2311 tmpbuf->data, tmpbuf->len, TRUE);
2313 /* Reprocess this packet after received reply from router */
2314 silc_server_command_pending(server, SILC_COMMAND_LIST,
2315 silc_command_get_ident(cmd->payload),
2316 silc_server_command_list,
2317 silc_server_command_dup(cmd));
2318 cmd->pending = TRUE;
2319 silc_command_set_ident(cmd->payload, old_ident);
2320 silc_buffer_free(tmpbuf);
2324 /* Get Channel ID */
2325 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2327 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2330 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2335 /* Get the channels from local list */
2336 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2339 /* Get the channels from global list */
2340 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2343 /* Send the reply */
2344 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2345 gchannels, gch_count);
2347 silc_free(lchannels);
2348 silc_free(gchannels);
2351 silc_server_command_free(cmd);
2354 /* Server side of TOPIC command. Sets topic for channel and/or returns
2355 current topic to client. */
2357 SILC_SERVER_CMD_FUNC(topic)
2359 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2360 SilcServer server = cmd->server;
2361 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2362 SilcChannelID *channel_id;
2363 SilcChannelEntry channel;
2364 SilcChannelClientEntry chl;
2365 SilcBuffer packet, idp;
2367 SilcUInt32 argc, tmp_len;
2368 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2370 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2372 argc = silc_argument_get_arg_num(cmd->args);
2374 /* Get Channel ID */
2375 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2377 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2378 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2381 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2384 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2388 /* Check whether the channel exists */
2389 channel = silc_idlist_find_channel_by_id(server->local_list,
2392 channel = silc_idlist_find_channel_by_id(server->global_list,
2395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2396 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2404 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2406 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2407 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2412 if (strlen(tmp) > 256) {
2413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2414 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2419 /* See whether the client is on channel and has rights to change topic */
2420 if (!silc_server_client_on_channel(client, channel, &chl)) {
2421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2422 SILC_STATUS_ERR_NOT_ON_CHANNEL,
2427 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2428 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2429 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2431 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2436 /* Set the topic for channel */
2437 silc_free(channel->topic);
2438 channel->topic = strdup(tmp);
2440 /* Send TOPIC_SET notify type to the network */
2441 if (!server->standalone)
2442 silc_server_send_notify_topic_set(server, server->router->connection,
2443 server->server_type == SILC_ROUTER ?
2444 TRUE : FALSE, channel,
2445 client->id, SILC_ID_CLIENT,
2448 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2450 /* Send notify about topic change to all clients on the channel */
2451 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2452 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2453 idp->data, idp->len,
2454 channel->topic, strlen(channel->topic));
2455 silc_buffer_free(idp);
2458 /* Send the topic to client as reply packet */
2459 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2460 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2461 SILC_STATUS_OK, 0, ident, 2,
2462 2, idp->data, idp->len,
2465 strlen(channel->topic) : 0);
2466 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2467 0, packet->data, packet->len, FALSE);
2469 silc_buffer_free(packet);
2470 silc_buffer_free(idp);
2471 silc_free(channel_id);
2474 silc_server_command_free(cmd);
2477 /* Server side of INVITE command. Invites some client to join some channel.
2478 This command is also used to manage the invite list of the channel. */
2480 SILC_SERVER_CMD_FUNC(invite)
2482 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2483 SilcServer server = cmd->server;
2484 SilcSocketConnection sock = cmd->sock, dest_sock;
2485 SilcChannelClientEntry chl;
2486 SilcClientEntry sender, dest;
2487 SilcClientID *dest_id = NULL;
2488 SilcChannelEntry channel;
2489 SilcChannelID *channel_id = NULL;
2490 SilcIDListData idata;
2491 SilcBuffer idp, idp2, packet;
2492 unsigned char *tmp, *add, *del;
2494 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2496 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2498 /* Get Channel ID */
2499 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2502 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2505 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2508 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2512 /* Get the channel entry */
2513 channel = silc_idlist_find_channel_by_id(server->local_list,
2516 channel = silc_idlist_find_channel_by_id(server->global_list,
2519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2520 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2526 /* Check whether the sender of this command is on the channel. */
2527 sender = (SilcClientEntry)sock->user_data;
2528 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2530 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2534 /* Check whether the channel is invite-only channel. If yes then the
2535 sender of this command must be at least channel operator. */
2536 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2537 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2538 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2540 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2545 /* Get destination client ID */
2546 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2551 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2553 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2554 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2558 /* Get the client entry */
2559 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2561 if (server->server_type != SILC_SERVER || !resolve) {
2562 silc_server_command_send_status_reply(
2563 cmd, SILC_COMMAND_INVITE,
2564 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2568 /* The client info is being resolved. Reprocess this packet after
2569 receiving the reply to the query. */
2570 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2572 silc_server_command_invite,
2573 silc_server_command_dup(cmd));
2574 cmd->pending = TRUE;
2575 silc_free(channel_id);
2580 /* Check whether the requested client is already on the channel. */
2581 if (silc_server_client_on_channel(dest, channel, NULL)) {
2582 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2583 SILC_STATUS_ERR_USER_ON_CHANNEL,
2588 /* Get route to the client */
2589 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2592 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2593 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2598 memset(invite, 0, sizeof(invite));
2599 strncat(invite, dest->nickname, strlen(dest->nickname));
2600 strncat(invite, "!", 1);
2601 strncat(invite, dest->username, strlen(dest->username));
2602 if (!strchr(dest->username, '@')) {
2603 strncat(invite, "@", 1);
2604 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2607 len = strlen(invite);
2608 if (!channel->invite_list)
2609 channel->invite_list = silc_calloc(len + 2,
2610 sizeof(*channel->invite_list));
2612 channel->invite_list = silc_realloc(channel->invite_list,
2613 sizeof(*channel->invite_list) *
2615 strlen(channel->invite_list) + 2));
2616 strncat(channel->invite_list, invite, len);
2617 strncat(channel->invite_list, ",", 1);
2619 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2620 /* Send notify to the client that is invited to the channel */
2621 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2622 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2623 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2625 SILC_NOTIFY_TYPE_INVITE, 3,
2626 idp->data, idp->len,
2627 channel->channel_name,
2628 strlen(channel->channel_name),
2629 idp2->data, idp2->len);
2630 silc_buffer_free(idp);
2631 silc_buffer_free(idp2);
2635 /* Add the client to the invite list of the channel */
2636 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2638 if (!channel->invite_list)
2639 channel->invite_list = silc_calloc(len + 2,
2640 sizeof(*channel->invite_list));
2642 channel->invite_list = silc_realloc(channel->invite_list,
2643 sizeof(*channel->invite_list) *
2645 strlen(channel->invite_list) + 2));
2646 if (add[len - 1] == ',')
2647 add[len - 1] = '\0';
2649 strncat(channel->invite_list, add, len);
2650 strncat(channel->invite_list, ",", 1);
2653 /* Get the invite to be removed and remove it from the list */
2654 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2655 if (del && channel->invite_list) {
2656 char *start, *end, *n;
2658 if (!strncmp(channel->invite_list, del,
2659 strlen(channel->invite_list) - 1)) {
2660 silc_free(channel->invite_list);
2661 channel->invite_list = NULL;
2663 start = strstr(channel->invite_list, del);
2664 if (start && strlen(start) >= len) {
2666 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2667 strncat(n, channel->invite_list, start - channel->invite_list);
2668 strncat(n, end + 1, ((channel->invite_list +
2669 strlen(channel->invite_list)) - end) - 1);
2670 silc_free(channel->invite_list);
2671 channel->invite_list = n;
2676 /* Send notify to the primary router */
2677 if (!server->standalone)
2678 silc_server_send_notify_invite(server, server->router->connection,
2679 server->server_type == SILC_ROUTER ?
2680 TRUE : FALSE, channel,
2681 sender->id, add, del);
2683 /* Send command reply */
2684 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2688 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2689 SILC_STATUS_OK, 0, ident, 2,
2691 3, channel->invite_list,
2692 channel->invite_list ?
2693 strlen(channel->invite_list) : 0);
2696 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2697 SILC_STATUS_OK, 0, ident, 1,
2699 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2700 packet->data, packet->len, FALSE);
2701 silc_buffer_free(packet);
2705 silc_free(channel_id);
2706 silc_server_command_free(cmd);
2711 SilcSocketConnection sock;
2715 /* Quits connection to client. This gets called if client won't
2716 close the connection even when it has issued QUIT command. */
2718 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2720 QuitInternal q = (QuitInternal)context;
2722 /* Free all client specific data, such as client entry and entires
2723 on channels this client may be on. */
2724 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2726 q->sock->user_data = NULL;
2728 /* Close the connection on our side */
2729 silc_server_close_connection(q->server, q->sock);
2731 silc_free(q->signoff);
2735 /* Quits SILC session. This is the normal way to disconnect client. */
2737 SILC_SERVER_CMD_FUNC(quit)
2739 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2740 SilcServer server = cmd->server;
2741 SilcSocketConnection sock = cmd->sock;
2743 unsigned char *tmp = NULL;
2746 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2748 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2752 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2756 q = silc_calloc(1, sizeof(*q));
2759 q->signoff = tmp ? strdup(tmp) : NULL;
2761 /* We quit the connection with little timeout */
2762 silc_schedule_task_add(server->schedule, sock->sock,
2763 silc_server_command_quit_cb, (void *)q,
2764 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2767 silc_server_command_free(cmd);
2770 /* Server side of command KILL. This command is used by router operator
2771 to remove an client from the SILC Network temporarily. */
2773 SILC_SERVER_CMD_FUNC(kill)
2775 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2776 SilcServer server = cmd->server;
2777 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2778 SilcClientEntry remote_client;
2779 SilcClientID *client_id;
2780 unsigned char *tmp, *comment;
2781 SilcUInt32 tmp_len, tmp_len2;
2784 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2786 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2789 /* KILL command works only on router */
2790 if (server->server_type != SILC_ROUTER) {
2791 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2792 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2796 /* Check whether client has the permissions. */
2797 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2798 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2799 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2803 /* Get the client ID */
2804 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2806 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2807 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2811 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2814 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2819 /* Get the client entry */
2820 remote_client = silc_idlist_find_client_by_id(server->local_list,
2821 client_id, TRUE, NULL);
2823 if (!remote_client) {
2824 remote_client = silc_idlist_find_client_by_id(server->global_list,
2825 client_id, TRUE, NULL);
2827 if (!remote_client) {
2828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2829 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2836 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2840 /* Send reply to the sender */
2841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2844 /* Check if anyone is watching this nickname */
2845 if (server->server_type == SILC_ROUTER)
2846 silc_server_check_watcher_list(server, client, NULL,
2847 SILC_NOTIFY_TYPE_KILLED);
2849 /* Now do the killing */
2850 silc_server_kill_client(server, remote_client, comment, client->id,
2854 silc_server_command_free(cmd);
2857 /* Server side of command INFO. This sends information about us to
2858 the client. If client requested specific server we will send the
2859 command to that server. */
2861 SILC_SERVER_CMD_FUNC(info)
2863 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2864 SilcServer server = cmd->server;
2865 SilcBuffer packet, idp;
2868 char *dest_server, *server_info = NULL, *server_name;
2869 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2870 SilcServerEntry entry = NULL;
2871 SilcServerID *server_id = NULL;
2873 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2875 /* Get server name */
2876 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2879 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2881 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2883 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2884 SILC_STATUS_ERR_NO_SERVER_ID, 0);
2890 /* Check whether we have this server cached */
2891 entry = silc_idlist_find_server_by_id(server->local_list,
2892 server_id, TRUE, NULL);
2894 entry = silc_idlist_find_server_by_id(server->global_list,
2895 server_id, TRUE, NULL);
2896 if (!entry && server->server_type != SILC_SERVER) {
2897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2898 SILC_STATUS_ERR_NO_SUCH_SERVER,
2905 /* Some buggy servers has sent request to router about themselves. */
2906 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2909 if ((!dest_server && !server_id && !entry) || (entry &&
2910 entry == server->id_entry) ||
2911 (dest_server && !cmd->pending &&
2912 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2913 /* Send our reply */
2914 char info_string[256];
2916 memset(info_string, 0, sizeof(info_string));
2917 snprintf(info_string, sizeof(info_string),
2918 "location: %s server: %s admin: %s <%s>",
2919 server->config->server_info->location,
2920 server->config->server_info->server_type,
2921 server->config->server_info->admin,
2922 server->config->server_info->email);
2924 server_info = info_string;
2925 entry = server->id_entry;
2927 /* Check whether we have this server cached */
2928 if (!entry && dest_server) {
2929 entry = silc_idlist_find_server_by_name(server->global_list,
2930 dest_server, TRUE, NULL);
2932 entry = silc_idlist_find_server_by_name(server->local_list,
2933 dest_server, TRUE, NULL);
2937 if (!cmd->pending &&
2938 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2939 /* Send to the server */
2941 SilcUInt16 old_ident;
2943 old_ident = silc_command_get_ident(cmd->payload);
2944 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2945 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2947 silc_server_packet_send(server, entry->connection,
2948 SILC_PACKET_COMMAND, cmd->packet->flags,
2949 tmpbuf->data, tmpbuf->len, TRUE);
2951 /* Reprocess this packet after received reply from router */
2952 silc_server_command_pending(server, SILC_COMMAND_INFO,
2953 silc_command_get_ident(cmd->payload),
2954 silc_server_command_info,
2955 silc_server_command_dup(cmd));
2956 cmd->pending = TRUE;
2957 silc_command_set_ident(cmd->payload, old_ident);
2958 silc_buffer_free(tmpbuf);
2962 if (!entry && !cmd->pending && !server->standalone) {
2963 /* Send to the primary router */
2965 SilcUInt16 old_ident;
2967 old_ident = silc_command_get_ident(cmd->payload);
2968 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2969 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2971 silc_server_packet_send(server, server->router->connection,
2972 SILC_PACKET_COMMAND, cmd->packet->flags,
2973 tmpbuf->data, tmpbuf->len, TRUE);
2975 /* Reprocess this packet after received reply from router */
2976 silc_server_command_pending(server, SILC_COMMAND_INFO,
2977 silc_command_get_ident(cmd->payload),
2978 silc_server_command_info,
2979 silc_server_command_dup(cmd));
2980 cmd->pending = TRUE;
2981 silc_command_set_ident(cmd->payload, old_ident);
2982 silc_buffer_free(tmpbuf);
2987 silc_free(server_id);
2990 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2991 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2995 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2997 server_info = entry->server_info;
2998 server_name = entry->server_name;
3000 /* Send the reply */
3001 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3002 SILC_STATUS_OK, 0, ident, 3,
3003 2, idp->data, idp->len,
3005 strlen(server_name),
3008 strlen(server_info) : 0);
3009 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3010 packet->data, packet->len, FALSE);
3012 silc_buffer_free(packet);
3013 silc_buffer_free(idp);
3016 silc_server_command_free(cmd);
3019 /* Server side of command PING. This just replies to the ping. */
3021 SILC_SERVER_CMD_FUNC(ping)
3023 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3024 SilcServer server = cmd->server;
3029 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3032 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3035 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3038 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3042 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3043 /* Send our reply */
3044 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3047 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3048 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3055 silc_server_command_free(cmd);
3058 /* Server side of command STATS. */
3060 SILC_SERVER_CMD_FUNC(stats)
3062 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3063 SilcServer server = cmd->server;
3064 SilcServerID *server_id;
3067 SilcBuffer packet, stats;
3068 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3071 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3074 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3076 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3077 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3080 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3084 /* The ID must be ours */
3085 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3086 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3087 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3088 silc_free(server_id);
3091 silc_free(server_id);
3093 /* If we are router then just send everything we got. If we are normal
3094 server then we'll send this to our router to get all the latest
3095 statistical information. */
3096 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3097 !server->standalone) {
3098 /* Send request to our router */
3099 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3101 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3102 ++server->cmd_ident, 1,
3103 1, idp->data, idp->len);
3104 silc_server_packet_send(server, server->router->connection,
3105 SILC_PACKET_COMMAND, 0, packet->data,
3106 packet->len, FALSE);
3108 /* Reprocess this packet after received reply from router */
3109 silc_server_command_pending(server, SILC_COMMAND_STATS,
3111 silc_server_command_stats,
3112 silc_server_command_dup(cmd));
3113 cmd->pending = TRUE;
3114 silc_buffer_free(packet);
3115 silc_buffer_free(idp);
3119 /* Send our reply to sender */
3120 uptime = time(NULL) - server->starttime;
3122 stats = silc_buffer_alloc_size(60);
3123 silc_buffer_format(stats,
3124 SILC_STR_UI_INT(server->starttime),
3125 SILC_STR_UI_INT(uptime),
3126 SILC_STR_UI_INT(server->stat.my_clients),
3127 SILC_STR_UI_INT(server->stat.my_channels),
3128 SILC_STR_UI_INT(server->stat.my_server_ops),
3129 SILC_STR_UI_INT(server->stat.my_router_ops),
3130 SILC_STR_UI_INT(server->stat.cell_clients),
3131 SILC_STR_UI_INT(server->stat.cell_channels),
3132 SILC_STR_UI_INT(server->stat.cell_servers),
3133 SILC_STR_UI_INT(server->stat.clients),
3134 SILC_STR_UI_INT(server->stat.channels),
3135 SILC_STR_UI_INT(server->stat.servers),
3136 SILC_STR_UI_INT(server->stat.routers),
3137 SILC_STR_UI_INT(server->stat.server_ops),
3138 SILC_STR_UI_INT(server->stat.router_ops),
3141 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3142 SILC_STATUS_OK, 0, ident, 2,
3144 3, stats->data, stats->len);
3145 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3146 0, packet->data, packet->len, FALSE);
3147 silc_buffer_free(packet);
3148 silc_buffer_free(stats);
3151 silc_server_command_free(cmd);
3154 /* Internal routine to join channel. The channel sent to this function
3155 has been either created or resolved from ID lists. This joins the sent
3156 client to the channel. */
3158 static void silc_server_command_join_channel(SilcServer server,
3159 SilcServerCommandContext cmd,
3160 SilcChannelEntry channel,
3161 SilcClientID *client_id,
3165 const unsigned char *auth,
3166 SilcUInt32 auth_len)
3168 SilcSocketConnection sock = cmd->sock;
3170 SilcUInt32 tmp_len, user_count;
3171 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3172 SilcClientEntry client;
3173 SilcChannelClientEntry chl;
3174 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3175 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3176 char check[512], check2[512];
3177 bool founder = FALSE;
3179 unsigned char *fkey = NULL;
3180 SilcUInt32 fkey_len = 0;
3182 SILC_LOG_DEBUG(("Start"));
3187 /* Get the client entry */
3188 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3189 client = (SilcClientEntry)sock->user_data;
3191 client = silc_server_get_client_resolve(server, client_id, FALSE,
3198 silc_server_command_send_status_reply(
3199 cmd, SILC_COMMAND_JOIN,
3200 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3204 /* The client info is being resolved. Reprocess this packet after
3205 receiving the reply to the query. */
3206 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3208 silc_server_command_join,
3209 silc_server_command_dup(cmd));
3210 cmd->pending = TRUE;
3214 cmd->pending = FALSE;
3218 * Check founder auth payload if provided. If client can gain founder
3219 * privileges it can override various conditions on joining the channel,
3220 * and can have directly the founder mode set on the channel.
3222 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3223 SilcIDListData idata = (SilcIDListData)client;
3225 if (channel->founder_key && idata->public_key &&
3226 silc_pkcs_public_key_compare(channel->founder_key,
3227 idata->public_key)) {
3228 /* Check whether the client is to become founder */
3229 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3230 channel->founder_key, 0, server->sha1hash,
3231 client->id, SILC_ID_CLIENT)) {
3232 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3239 * Check channel modes
3243 memset(check, 0, sizeof(check));
3244 memset(check2, 0, sizeof(check2));
3245 strncat(check, client->nickname, strlen(client->nickname));
3246 strncat(check, "!", 1);
3247 strncat(check, client->username, strlen(client->username));
3248 if (!strchr(client->username, '@')) {
3249 strncat(check, "@", 1);
3250 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3253 strncat(check2, client->nickname, strlen(client->nickname));
3254 if (!strchr(client->nickname, '@')) {
3255 strncat(check2, "@", 1);
3256 strncat(check2, server->server_name, strlen(server->server_name));
3258 strncat(check2, "!", 1);
3259 strncat(check2, client->username, strlen(client->username));
3260 if (!strchr(client->username, '@')) {
3261 strncat(check2, "@", 1);
3262 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3265 /* Check invite list if channel is invite-only channel */
3266 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3267 if (!channel->invite_list ||
3268 (!silc_string_match(channel->invite_list, check) &&
3269 !silc_string_match(channel->invite_list, check2))) {
3270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3271 SILC_STATUS_ERR_NOT_INVITED, 0);
3276 /* Check ban list if it exists. If the client's nickname, server,
3277 username and/or hostname is in the ban list the access to the
3278 channel is denied. */
3279 if (channel->ban_list) {
3280 if (silc_string_match(channel->ban_list, check) ||
3281 silc_string_match(channel->ban_list, check2)) {
3282 silc_server_command_send_status_reply(
3283 cmd, SILC_COMMAND_JOIN,
3284 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3289 /* Check user count limit if set. */
3290 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3291 if (silc_hash_table_count(channel->user_list) + 1 >
3292 channel->user_limit) {
3293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3294 SILC_STATUS_ERR_CHANNEL_IS_FULL,
3301 /* Check the channel passphrase if set. */
3302 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3303 /* Get passphrase */
3304 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3306 passphrase = silc_memdup(tmp, tmp_len);
3308 if (!passphrase || !channel->passphrase ||
3309 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3311 SILC_STATUS_ERR_BAD_PASSWORD, 0);
3317 * Client is allowed to join to the channel. Make it happen.
3320 /* Check whether the client already is on the channel */
3321 if (silc_server_client_on_channel(client, channel, NULL)) {
3322 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3323 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3327 /* Generate new channel key as protocol dictates */
3329 if (!silc_server_create_channel_key(server, channel, 0))
3332 /* Send the channel key. This is broadcasted to the channel but is not
3333 sent to the client who is joining to the channel. */
3334 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3335 silc_server_send_channel_key(server, NULL, channel,
3336 server->server_type == SILC_ROUTER ?
3337 FALSE : !server->standalone);
3340 /* Join the client to the channel by adding it to channel's user list.
3341 Add also the channel to client entry's channels list for fast cross-
3343 chl = silc_calloc(1, sizeof(*chl));
3345 chl->client = client;
3346 chl->channel = channel;
3347 silc_hash_table_add(channel->user_list, client, chl);
3348 silc_hash_table_add(client->channels, channel, chl);
3349 channel->user_count++;
3350 channel->disabled = FALSE;
3352 /* Get users on the channel */
3353 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3356 /* Encode Client ID Payload of the original client who wants to join */
3357 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3359 /* Encode command reply packet */
3360 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3361 SILC_PUT32_MSB(channel->mode, mode);
3362 SILC_PUT32_MSB(created, tmp2);
3363 SILC_PUT32_MSB(user_count, tmp3);
3365 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3366 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3367 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3370 strlen(channel->channel_key->
3372 channel->channel_key->cipher->name,
3373 channel->key_len / 8, channel->key);
3377 if (channel->founder_key)
3378 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3381 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3382 SILC_STATUS_OK, 0, ident, 14,
3383 2, channel->channel_name,
3384 strlen(channel->channel_name),
3385 3, chidp->data, chidp->len,
3386 4, clidp->data, clidp->len,
3389 7, keyp ? keyp->data : NULL,
3390 keyp ? keyp->len : 0,
3391 8, channel->ban_list,
3393 strlen(channel->ban_list) : 0,
3394 9, channel->invite_list,
3395 channel->invite_list ?
3396 strlen(channel->invite_list) : 0,
3399 strlen(channel->topic) : 0,
3400 11, silc_hmac_get_name(channel->hmac),
3401 strlen(silc_hmac_get_name(channel->
3404 13, user_list->data, user_list->len,
3405 14, mode_list->data,
3407 15, fkey, fkey_len);
3409 /* Send command reply */
3410 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3411 reply->data, reply->len, FALSE);
3413 /* Send JOIN notify to locally connected clients on the channel. If
3414 we are normal server then router will send or have sent JOIN notify
3415 already. However since we've added the client already to our channel
3416 we'll ignore it (in packet_receive.c) so we must send it here. If
3417 we are router then this will send it to local clients and local
3419 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3420 SILC_NOTIFY_TYPE_JOIN, 2,
3421 clidp->data, clidp->len,
3422 chidp->data, chidp->len);
3424 if (!cmd->pending) {
3425 /* Send JOIN notify packet to our primary router */
3426 if (!server->standalone)
3427 silc_server_send_notify_join(server, server->router->connection,
3428 server->server_type == SILC_ROUTER ?
3429 TRUE : FALSE, channel, client->id);
3432 /* Distribute the channel key to all backup routers. */
3433 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3434 keyp->data, keyp->len, FALSE, TRUE);
3436 /* If client became founder by providing correct founder auth data
3437 notify the mode change to the channel. */
3439 SILC_PUT32_MSB(chl->mode, mode);
3440 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3441 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3442 clidp->data, clidp->len,
3443 mode, 4, clidp->data, clidp->len,
3446 /* Set CUMODE notify type to network */
3447 if (!server->standalone)
3448 silc_server_send_notify_cumode(server, server->router->connection,
3449 server->server_type == SILC_ROUTER ?
3450 TRUE : FALSE, channel,
3451 chl->mode, client->id, SILC_ID_CLIENT,
3452 client->id, channel->founder_key);
3456 silc_buffer_free(reply);
3457 silc_buffer_free(clidp);
3458 silc_buffer_free(chidp);
3459 silc_buffer_free(keyp);
3460 silc_buffer_free(user_list);
3461 silc_buffer_free(mode_list);
3465 silc_free(passphrase);
3468 /* Server side of command JOIN. Joins client into requested channel. If
3469 the channel does not exist it will be created. */
3471 SILC_SERVER_CMD_FUNC(join)
3473 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3474 SilcServer server = cmd->server;
3475 unsigned char *auth;
3476 SilcUInt32 tmp_len, auth_len;
3477 char *tmp, *channel_name = NULL, *cipher, *hmac;
3478 SilcChannelEntry channel;
3479 SilcUInt32 umode = 0;
3480 bool created = FALSE, create_key = TRUE;
3481 SilcClientID *client_id;
3483 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3485 /* Get channel name */
3486 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3489 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3496 channel_name[255] = '\0';
3498 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3500 SILC_STATUS_ERR_BAD_CHANNEL, 0);
3504 /* Get Client ID of the client who is joining to the channel */
3505 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3508 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3512 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3515 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3520 /* Get cipher, hmac name and auth payload */
3521 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3522 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3523 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3525 /* See if the channel exists */
3526 channel = silc_idlist_find_channel_by_name(server->local_list,
3527 channel_name, NULL);
3529 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3530 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3531 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3534 (channel->disabled && server->server_type != SILC_ROUTER)) {
3535 /* Channel not found */
3537 /* If we are standalone server we don't have a router, we just create
3538 the channel by ourselves. */
3539 if (server->standalone) {
3540 channel = silc_server_create_new_channel(server, server->id, cipher,
3541 hmac, channel_name, TRUE);
3543 silc_server_command_send_status_reply(
3544 cmd, SILC_COMMAND_JOIN,
3545 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3550 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3556 /* The channel does not exist on our server. If we are normal server
3557 we will send JOIN command to our router which will handle the
3558 joining procedure (either creates the channel if it doesn't exist
3559 or joins the client to it). */
3560 if (server->server_type != SILC_ROUTER) {
3562 SilcUInt16 old_ident;
3564 /* If this is pending command callback then we've resolved
3565 it and it didn't work, return since we've notified the
3566 client already in the command reply callback. */
3570 old_ident = silc_command_get_ident(cmd->payload);
3571 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3572 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3574 /* Send JOIN command to our router */
3575 silc_server_packet_send(server, (SilcSocketConnection)
3576 server->router->connection,
3577 SILC_PACKET_COMMAND, cmd->packet->flags,
3578 tmpbuf->data, tmpbuf->len, TRUE);
3580 /* Reprocess this packet after received reply from router */
3581 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3582 silc_command_get_ident(cmd->payload),
3583 silc_server_command_join,
3584 silc_server_command_dup(cmd));
3585 cmd->pending = TRUE;
3586 silc_command_set_ident(cmd->payload, old_ident);
3587 silc_buffer_free(tmpbuf);
3591 /* We are router and the channel does not seem exist so we will check
3592 our global list as well for the channel. */
3593 channel = silc_idlist_find_channel_by_name(server->global_list,
3594 channel_name, NULL);
3596 /* Channel really does not exist, create it */
3597 channel = silc_server_create_new_channel(server, server->id, cipher,
3598 hmac, channel_name, TRUE);
3600 silc_server_command_send_status_reply(
3601 cmd, SILC_COMMAND_JOIN,
3602 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3606 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3614 /* Channel not found */
3616 /* If the command came from router and we are normal server then
3617 something went wrong with the joining as the channel was not found.
3618 We can't do anything else but ignore this. */
3619 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3620 server->server_type != SILC_ROUTER)
3623 /* We are router and the channel does not seem exist so we will check
3624 our global list as well for the channel. */
3625 channel = silc_idlist_find_channel_by_name(server->global_list,
3626 channel_name, NULL);
3628 /* Channel really does not exist, create it */
3629 channel = silc_server_create_new_channel(server, server->id, cipher,
3630 hmac, channel_name, TRUE);
3632 silc_server_command_send_status_reply(
3633 cmd, SILC_COMMAND_JOIN,
3634 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3638 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3645 /* Check whether the channel was created by our router */
3646 if (cmd->pending && context2) {
3647 SilcServerCommandReplyContext reply = context2;
3649 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3650 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3651 SILC_GET32_MSB(created, tmp);
3652 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3653 create_key = FALSE; /* Router returned the key already */
3656 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3657 !channel->disabled && !silc_hash_table_count(channel->user_list))
3661 /* If the channel does not have global users and is also empty the client
3662 will be the channel founder and operator. */
3663 if (!channel->disabled &&
3664 !channel->global_users && !silc_hash_table_count(channel->user_list))
3665 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3667 /* Join to the channel */
3668 silc_server_command_join_channel(server, cmd, channel, client_id,
3669 created, create_key, umode,
3672 silc_free(client_id);
3675 silc_server_command_free(cmd);
3678 /* Server side of command MOTD. Sends server's current "message of the
3679 day" to the client. */
3681 SILC_SERVER_CMD_FUNC(motd)
3683 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3684 SilcServer server = cmd->server;
3685 SilcBuffer packet, idp;
3686 char *motd, *dest_server;
3687 SilcUInt32 motd_len;
3688 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3690 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3692 /* Get server name */
3693 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3696 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3700 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3703 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3705 if (server->config && server->config->server_info &&
3706 server->config->server_info->motd_file) {
3708 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3713 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3720 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3726 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3727 packet->data, packet->len, FALSE);
3728 silc_buffer_free(packet);
3729 silc_buffer_free(idp);
3731 SilcServerEntry entry;
3733 /* Check whether we have this server cached */
3734 entry = silc_idlist_find_server_by_name(server->global_list,
3735 dest_server, TRUE, NULL);
3737 entry = silc_idlist_find_server_by_name(server->local_list,
3738 dest_server, TRUE, NULL);
3741 if (server->server_type != SILC_SERVER && !cmd->pending &&
3742 entry && !entry->motd) {
3743 /* Send to the server */
3745 SilcUInt16 old_ident;
3747 old_ident = silc_command_get_ident(cmd->payload);
3748 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3749 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3751 silc_server_packet_send(server, entry->connection,
3752 SILC_PACKET_COMMAND, cmd->packet->flags,
3753 tmpbuf->data, tmpbuf->len, TRUE);
3755 /* Reprocess this packet after received reply from router */
3756 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3757 silc_command_get_ident(cmd->payload),
3758 silc_server_command_motd,
3759 silc_server_command_dup(cmd));
3760 cmd->pending = TRUE;
3761 silc_command_set_ident(cmd->payload, old_ident);
3762 silc_buffer_free(tmpbuf);
3766 if (!entry && !cmd->pending && !server->standalone) {
3767 /* Send to the primary router */
3769 SilcUInt16 old_ident;
3771 old_ident = silc_command_get_ident(cmd->payload);
3772 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3773 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3775 silc_server_packet_send(server, server->router->connection,
3776 SILC_PACKET_COMMAND, cmd->packet->flags,
3777 tmpbuf->data, tmpbuf->len, TRUE);
3779 /* Reprocess this packet after received reply from router */
3780 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3781 silc_command_get_ident(cmd->payload),
3782 silc_server_command_motd,
3783 silc_server_command_dup(cmd));
3784 cmd->pending = TRUE;
3785 silc_command_set_ident(cmd->payload, old_ident);
3786 silc_buffer_free(tmpbuf);
3791 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3792 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3796 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3797 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3798 SILC_STATUS_OK, 0, ident, 2,
3802 strlen(entry->motd) : 0);
3803 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3804 packet->data, packet->len, FALSE);
3805 silc_buffer_free(packet);
3806 silc_buffer_free(idp);
3810 silc_server_command_free(cmd);
3813 /* Server side of command UMODE. Client can use this command to set/unset
3814 user mode. Client actually cannot set itself to be as server/router
3815 operator so this can be used only to unset the modes. */
3817 SILC_SERVER_CMD_FUNC(umode)
3819 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3820 SilcServer server = cmd->server;
3821 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3823 unsigned char *tmp_mask, m[4];
3824 SilcUInt32 mask = 0;
3825 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3826 bool set_mask = FALSE;
3828 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3831 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3833 /* Get the client's mode mask */
3834 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3836 SILC_GET32_MSB(mask, tmp_mask);
3841 /* Check that mode changing is allowed. */
3842 if (!silc_server_check_umode_rights(server, client, mask)) {
3843 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3844 SILC_STATUS_ERR_PERM_DENIED, 0);
3848 /* Anonymous mode cannot be set by client */
3849 if (mask & SILC_UMODE_ANONYMOUS) {
3850 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3851 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3852 SILC_STATUS_ERR_PERM_DENIED, 0);
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);
3863 /* Change the mode */
3864 client->mode = mask;
3866 /* Send UMODE change to primary router */
3867 if (!server->standalone)
3868 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3869 client->id, client->mode);
3871 /* Check if anyone is watching this nickname */
3872 if (server->server_type == SILC_ROUTER)
3873 silc_server_check_watcher_list(server, client, NULL,
3874 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3877 /* Send command reply to sender */
3878 SILC_PUT32_MSB(client->mode, m);
3879 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3880 SILC_STATUS_OK, 0, ident, 1,
3882 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3883 packet->data, packet->len, FALSE);
3884 silc_buffer_free(packet);
3887 silc_server_command_free(cmd);
3890 /* Server side command of CMODE. Changes channel mode */
3892 SILC_SERVER_CMD_FUNC(cmode)
3894 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3895 SilcServer server = cmd->server;
3896 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3897 SilcIDListData idata = (SilcIDListData)client;
3898 SilcChannelID *channel_id = NULL;
3899 SilcChannelEntry channel;
3900 SilcChannelClientEntry chl;
3901 SilcBuffer packet, cidp;
3902 unsigned char *tmp, *tmp_id, *tmp_mask;
3903 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3904 SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3905 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3906 bool set_mask = FALSE;
3907 SilcPublicKey founder_key = NULL;
3908 unsigned char *fkey = NULL;
3909 SilcUInt32 fkey_len = 0;
3911 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3913 /* Get Channel ID */
3914 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3916 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3917 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3920 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3922 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3923 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3927 /* Get the channel mode mask */
3928 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3930 SILC_GET32_MSB(mode_mask, tmp_mask);
3934 /* Get channel entry */
3935 channel = silc_idlist_find_channel_by_id(server->local_list,
3938 channel = silc_idlist_find_channel_by_id(server->global_list,
3941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3942 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3948 /* Check whether this client is on the channel */
3949 if (!silc_server_client_on_channel(client, channel, &chl)) {
3950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3951 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3955 /* Check that client has rights to change any requested channel modes */
3956 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
3958 silc_server_command_send_status_reply(
3959 cmd, SILC_COMMAND_CMODE,
3960 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
3961 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3962 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
3966 /* If mode mask was not sent as argument then merely return the current
3967 mode mask to the sender. */
3970 SILC_PUT32_MSB(channel->mode, m);
3971 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3972 SILC_STATUS_OK, 0, ident, 2,
3973 2, tmp_id, tmp_len2,
3975 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3976 packet->data, packet->len, FALSE);
3977 silc_buffer_free(packet);
3982 * Check the modes. Modes that requires nothing special operation are
3986 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3987 /* Channel uses private keys to protect traffic. Client(s) has set the
3988 key locally they want to use, server does not know that key. */
3989 /* Nothing interesting to do here */
3991 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3992 /* The mode is removed and we need to generate and distribute
3993 new channel key. Clients are not using private channel keys
3994 anymore after this. */
3996 /* Re-generate channel key */
3997 if (!silc_server_create_channel_key(server, channel, 0))
4000 /* Send the channel key. This sends it to our local clients and if
4001 we are normal server to our router as well. */
4002 silc_server_send_channel_key(server, NULL, channel,
4003 server->server_type == SILC_ROUTER ?
4004 FALSE : !server->standalone);
4006 cipher = channel->channel_key->cipher->name;
4007 hmac = (char *)silc_hmac_get_name(channel->hmac);
4011 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4012 /* User limit is set on channel */
4013 SilcUInt32 user_limit;
4015 /* Get user limit */
4016 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4018 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4019 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4020 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4024 SILC_GET32_MSB(user_limit, tmp);
4025 channel->user_limit = user_limit;
4028 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4029 /* User limit mode is unset. Remove user limit */
4030 channel->user_limit = 0;
4033 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4034 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4035 /* Passphrase has been set to channel */
4037 /* Get the passphrase */
4038 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4040 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4041 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4045 /* Save the passphrase */
4046 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4049 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4050 /* Passphrase mode is unset. remove the passphrase */
4051 silc_free(channel->passphrase);
4052 channel->passphrase = NULL;
4056 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4057 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4058 /* Cipher to use protect the traffic */
4059 SilcCipher newkey, oldkey;
4062 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4064 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4065 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4069 /* Delete old cipher and allocate the new one */
4070 if (!silc_cipher_alloc(cipher, &newkey)) {
4071 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4072 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4076 oldkey = channel->channel_key;
4077 channel->channel_key = newkey;
4079 /* Re-generate channel key */
4080 if (!silc_server_create_channel_key(server, channel, 0)) {
4081 /* We don't have new key, revert to old one */
4082 channel->channel_key = oldkey;
4086 /* Remove old channel key for good */
4087 silc_cipher_free(oldkey);
4089 /* Send the channel key. This sends it to our local clients and if
4090 we are normal server to our router as well. */
4091 silc_server_send_channel_key(server, NULL, channel,
4092 server->server_type == SILC_ROUTER ?
4093 FALSE : !server->standalone);
4096 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4097 /* Cipher mode is unset. Remove the cipher and revert back to
4099 SilcCipher newkey, oldkey;
4100 cipher = channel->cipher;
4102 /* Delete old cipher and allocate default one */
4103 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4104 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4105 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4109 oldkey = channel->channel_key;
4110 channel->channel_key = newkey;
4112 /* Re-generate channel key */
4113 if (!silc_server_create_channel_key(server, channel, 0)) {
4114 /* We don't have new key, revert to old one */
4115 channel->channel_key = oldkey;
4119 /* Remove old channel key for good */
4120 silc_cipher_free(oldkey);
4122 /* Send the channel key. This sends it to our local clients and if
4123 we are normal server to our router as well. */
4124 silc_server_send_channel_key(server, NULL, channel,
4125 server->server_type == SILC_ROUTER ?
4126 FALSE : !server->standalone);
4130 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4131 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4132 /* HMAC to use protect the traffic */
4133 unsigned char hash[32];
4137 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4139 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4140 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4144 /* Delete old hmac and allocate the new one */
4145 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4146 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4147 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4151 silc_hmac_free(channel->hmac);
4152 channel->hmac = newhmac;
4154 /* Set the HMAC key out of current channel key. The client must do
4156 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4157 channel->key_len / 8, hash);
4158 silc_hmac_set_key(channel->hmac, hash,
4159 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4160 memset(hash, 0, sizeof(hash));
4163 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4164 /* Hmac mode is unset. Remove the hmac and revert back to
4167 unsigned char hash[32];
4168 hmac = channel->hmac_name;
4170 /* Delete old hmac and allocate default one */
4171 silc_hmac_free(channel->hmac);
4172 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4173 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4174 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4178 silc_hmac_free(channel->hmac);
4179 channel->hmac = newhmac;
4181 /* Set the HMAC key out of current channel key. The client must do
4183 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4184 channel->key_len / 8,
4186 silc_hmac_set_key(channel->hmac, hash,
4187 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4188 memset(hash, 0, sizeof(hash));
4192 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4193 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4194 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4195 /* Set the founder authentication */
4196 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4198 silc_server_command_send_status_reply(
4199 cmd, SILC_COMMAND_CMODE,
4200 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4204 /* Verify the payload before setting the mode */
4205 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4206 idata->public_key, 0, server->sha1hash,
4207 client->id, SILC_ID_CLIENT)) {
4208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4209 SILC_STATUS_ERR_AUTH_FAILED,
4214 /* Save the public key */
4215 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4216 if (!channel->founder_key) {
4217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4218 SILC_STATUS_ERR_AUTH_FAILED,
4223 founder_key = channel->founder_key;
4224 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4226 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4227 SILC_STATUS_ERR_AUTH_FAILED,
4234 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4235 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4236 if (channel->founder_key)
4237 silc_pkcs_public_key_free(channel->founder_key);
4238 channel->founder_key = NULL;
4243 /* Finally, set the mode */
4244 channel->mode = mode_mask;
4246 /* Send CMODE_CHANGE notify. */
4247 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4248 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4249 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4250 cidp->data, cidp->len,
4252 cipher, cipher ? strlen(cipher) : 0,
4253 hmac, hmac ? strlen(hmac) : 0,
4254 passphrase, passphrase ?
4255 strlen(passphrase) : 0,
4258 /* Set CMODE notify type to network */
4259 if (!server->standalone)
4260 silc_server_send_notify_cmode(server, server->router->connection,
4261 server->server_type == SILC_ROUTER ?
4262 TRUE : FALSE, channel,
4263 mode_mask, client->id, SILC_ID_CLIENT,
4264 cipher, hmac, passphrase, founder_key);
4266 /* Send command reply to sender */
4267 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4268 SILC_STATUS_OK, 0, ident, 2,
4269 2, tmp_id, tmp_len2,
4271 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4272 packet->data, packet->len, FALSE);
4274 silc_buffer_free(packet);
4275 silc_buffer_free(cidp);
4279 silc_free(channel_id);
4280 silc_server_command_free(cmd);
4283 /* Server side of CUMODE command. Changes client's mode on a channel. */
4285 SILC_SERVER_CMD_FUNC(cumode)
4287 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4288 SilcServer server = cmd->server;
4289 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4290 SilcIDListData idata = (SilcIDListData)client;
4291 SilcChannelID *channel_id;
4292 SilcClientID *client_id;
4293 SilcChannelEntry channel;
4294 SilcClientEntry target_client;
4295 SilcChannelClientEntry chl;
4296 SilcBuffer packet, idp;
4297 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4298 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4300 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4301 SilcPublicKey founder_key = NULL;
4302 unsigned char *fkey = NULL;
4303 SilcUInt32 fkey_len = 0;
4305 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4307 /* Get Channel ID */
4308 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4311 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4314 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4317 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4321 /* Get channel entry */
4322 channel = silc_idlist_find_channel_by_id(server->local_list,
4325 channel = silc_idlist_find_channel_by_id(server->global_list,
4328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4329 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4335 /* Check whether sender is on the channel */
4336 if (!silc_server_client_on_channel(client, channel, &chl)) {
4337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4338 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4341 sender_mask = chl->mode;
4343 /* Get the target client's channel mode mask */
4344 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4347 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4351 SILC_GET32_MSB(target_mask, tmp_mask);
4353 /* Get target Client ID */
4354 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4357 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4360 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4362 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4363 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4367 /* Get target client's entry */
4368 target_client = silc_idlist_find_client_by_id(server->local_list,
4369 client_id, TRUE, NULL);
4370 if (!target_client) {
4371 target_client = silc_idlist_find_client_by_id(server->global_list,
4372 client_id, TRUE, NULL);
4375 if (target_client != client &&
4376 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4377 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4378 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4379 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4383 /* Check whether target client is on the channel */
4384 if (target_client != client) {
4385 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4387 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4396 /* If the target client is founder, no one else can change their mode
4398 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4400 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4405 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4406 if (target_client != client) {
4407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4408 SILC_STATUS_ERR_NOT_YOU, 0);
4412 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4413 /* The client tries to claim the founder rights. */
4414 unsigned char *tmp_auth;
4415 SilcUInt32 tmp_auth_len;
4417 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4418 !channel->founder_key || !idata->public_key ||
4419 !silc_pkcs_public_key_compare(channel->founder_key,
4420 idata->public_key)) {
4421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4422 SILC_STATUS_ERR_AUTH_FAILED, 0);
4426 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4429 SILC_STATUS_ERR_AUTH_FAILED, 0);
4433 /* Verify the authentication payload */
4434 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4435 channel->founder_key, 0, server->sha1hash,
4436 client->id, SILC_ID_CLIENT)) {
4437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4438 SILC_STATUS_ERR_AUTH_FAILED, 0);
4442 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4444 founder_key = channel->founder_key;
4445 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4448 SILC_STATUS_ERR_AUTH_FAILED, 0);
4453 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4454 if (target_client == client) {
4455 /* Remove channel founder rights from itself */
4456 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4459 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4460 SILC_STATUS_ERR_NOT_YOU, 0);
4466 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4467 /* Promote to operator */
4468 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4469 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4470 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4471 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4472 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4477 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4481 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4482 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4483 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4484 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4485 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4490 /* Demote to normal user */
4491 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4496 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4497 if (target_client != client) {
4498 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4499 SILC_STATUS_ERR_NOT_YOU, 0);
4503 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4504 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4508 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4509 if (target_client != client) {
4510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4511 SILC_STATUS_ERR_NOT_YOU, 0);
4515 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4520 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4521 if (target_client != client) {
4522 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4523 SILC_STATUS_ERR_NOT_YOU, 0);
4527 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4528 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4532 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4533 if (target_client != client) {
4534 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4535 SILC_STATUS_ERR_NOT_YOU, 0);
4539 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4544 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4545 if (target_client != client) {
4546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4547 SILC_STATUS_ERR_NOT_YOU, 0);
4551 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4552 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4556 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4557 if (target_client != client) {
4558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4559 SILC_STATUS_ERR_NOT_YOU, 0);
4563 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4568 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4569 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4571 /* Send notify to channel, notify only if mode was actually changed. */
4573 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4574 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4575 idp->data, idp->len,
4580 /* Set CUMODE notify type to network */
4581 if (!server->standalone)
4582 silc_server_send_notify_cumode(server, server->router->connection,
4583 server->server_type == SILC_ROUTER ?
4584 TRUE : FALSE, channel,
4585 target_mask, client->id,
4587 target_client->id, founder_key);
4590 /* Send command reply to sender */
4591 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4592 SILC_STATUS_OK, 0, ident, 3,
4594 3, tmp_ch_id, tmp_ch_len,
4595 4, tmp_id, tmp_len);
4596 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4597 packet->data, packet->len, FALSE);
4599 silc_buffer_free(packet);
4600 silc_free(channel_id);
4601 silc_free(client_id);
4602 silc_buffer_free(idp);
4606 silc_server_command_free(cmd);
4609 /* Server side of KICK command. Kicks client out of channel. */
4611 SILC_SERVER_CMD_FUNC(kick)
4613 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4614 SilcServer server = cmd->server;
4615 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4616 SilcClientEntry target_client;
4617 SilcChannelID *channel_id;
4618 SilcClientID *client_id;
4619 SilcChannelEntry channel;
4620 SilcChannelClientEntry chl;
4622 SilcUInt32 tmp_len, target_idp_len;
4623 unsigned char *tmp, *comment, *target_idp;
4625 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4627 /* Get Channel ID */
4628 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4630 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4631 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4634 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4637 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4641 /* Get channel entry */
4642 channel = silc_idlist_find_channel_by_id(server->local_list,
4645 channel = silc_idlist_find_channel_by_id(server->local_list,
4648 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4649 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4655 /* Check whether sender is on the channel */
4656 if (!silc_server_client_on_channel(client, channel, &chl)) {
4657 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4658 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4662 /* Check that the kicker is channel operator or channel founder */
4663 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4664 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4665 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4666 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4670 /* Get target Client ID */
4671 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4674 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4677 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4680 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4684 /* Get target client's entry */
4685 target_client = silc_idlist_find_client_by_id(server->local_list,
4686 client_id, TRUE, NULL);
4687 if (!target_client) {
4688 target_client = silc_idlist_find_client_by_id(server->global_list,
4689 client_id, TRUE, NULL);
4692 /* Check whether target client is on the channel */
4693 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4695 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4700 /* Check that the target client is not channel founder. Channel founder
4701 cannot be kicked from the channel. */
4702 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4704 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4711 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4715 /* Send command reply to sender */
4716 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4719 /* Send KICKED notify to local clients on the channel */
4720 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4721 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4722 SILC_NOTIFY_TYPE_KICKED, 3,
4723 target_idp, target_idp_len,
4724 comment, comment ? strlen(comment) : 0,
4725 idp->data, idp->len);
4726 silc_buffer_free(idp);
4728 /* Remove the client from the channel. If the channel does not exist
4729 after removing the client then the client kicked itself off the channel
4730 and we don't have to send anything after that. */
4731 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4732 target_client, FALSE))
4735 /* Send KICKED notify to primary route */
4736 if (!server->standalone)
4737 silc_server_send_notify_kicked(server, server->router->connection,
4738 server->server_type == SILC_ROUTER ?
4739 TRUE : FALSE, channel,
4740 target_client->id, client->id, comment);
4742 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4743 /* Re-generate channel key */
4744 if (!silc_server_create_channel_key(server, channel, 0))
4747 /* Send the channel key to the channel. The key of course is not sent
4748 to the client who was kicked off the channel. */
4749 silc_server_send_channel_key(server, target_client->connection, channel,
4750 server->server_type == SILC_ROUTER ?
4751 FALSE : !server->standalone);
4755 silc_server_command_free(cmd);
4758 /* Server side of OPER command. Client uses this comand to obtain server
4759 operator privileges to this server/router. */
4761 SILC_SERVER_CMD_FUNC(oper)
4763 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4764 SilcServer server = cmd->server;
4765 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4766 unsigned char *username, *auth;
4768 SilcServerConfigAdmin *admin;
4769 SilcIDListData idata = (SilcIDListData)client;
4770 bool result = FALSE;
4771 SilcPublicKey cached_key;
4773 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4775 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4778 /* Get the username */
4779 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4781 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4782 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4787 /* Get the admin configuration */
4788 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4789 username, client->nickname);
4791 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4792 username, client->nickname);
4794 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4795 SILC_STATUS_ERR_AUTH_FAILED,
4801 /* Get the authentication payload */
4802 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4804 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4805 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4810 /* Verify the authentication data. If both passphrase and public key
4811 is set then try both of them. */
4812 if (admin->passphrase)
4813 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4814 admin->passphrase, admin->passphrase_len,
4815 idata->hash, client->id, SILC_ID_CLIENT);
4816 if (!result && admin->publickeys) {
4817 cached_key = silc_server_get_public_key(server, admin->publickeys);
4820 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4821 cached_key, 0, idata->hash,
4822 client->id, SILC_ID_CLIENT);
4825 /* Authentication failed */
4826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4827 SILC_STATUS_ERR_AUTH_FAILED,
4832 /* Client is now server operator */
4833 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4835 /* Update statistics */
4836 if (client->connection)
4837 server->stat.my_server_ops++;
4838 if (server->server_type == SILC_ROUTER)
4839 server->stat.server_ops++;
4841 /* Send UMODE change to primary router */
4842 if (!server->standalone)
4843 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4844 client->id, client->mode);
4846 /* Check if anyone is watching this nickname */
4847 if (server->server_type == SILC_ROUTER)
4848 silc_server_check_watcher_list(server, client, NULL,
4849 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4851 /* Send reply to the sender */
4852 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4856 silc_server_command_free(cmd);
4859 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4861 QuitInternal q = (QuitInternal)context;
4862 SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4864 /* If there is pending outgoing data for the client then purge it
4865 to the network before closing connection. */
4866 silc_server_packet_queue_purge(q->server, q->sock);
4868 /* Close the connection on our side */
4869 client->router = NULL;
4870 client->connection = NULL;
4871 q->sock->user_data = NULL;
4872 silc_server_close_connection(q->server, q->sock);
4877 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4879 QuitInternal q = (QuitInternal)context;
4880 SilcClientID *client_id = (SilcClientID *)q->sock;
4881 SilcClientEntry client;
4883 SILC_LOG_DEBUG(("Start"));
4885 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4888 if (client && client->mode & SILC_UMODE_DETACHED)
4889 silc_server_free_client_data(q->server, NULL, client, TRUE,
4892 silc_free(client_id);
4896 /* Server side of DETACH command. Detached the client from the network
4897 by closing the connection but preserving the session. */
4899 SILC_SERVER_CMD_FUNC(detach)
4901 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4902 SilcServer server = cmd->server;
4903 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4906 if (server->config->detach_disabled) {
4907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4908 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
4912 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4915 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4917 /* Send the user mode notify to notify that client is detached */
4918 client->mode |= SILC_UMODE_DETACHED;
4919 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4920 client->last_command = 0;
4921 client->fast_command = 0;
4922 if (!server->standalone)
4923 silc_server_send_notify_umode(server, server->router->connection,
4924 server->server_type == SILC_SERVER ?
4925 FALSE : TRUE, client->id, client->mode);
4927 /* Check if anyone is watching this nickname */
4928 if (server->server_type == SILC_ROUTER)
4929 silc_server_check_watcher_list(server, client, NULL,
4930 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4932 q = silc_calloc(1, sizeof(*q));
4934 q->sock = cmd->sock;
4935 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4936 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4938 if (server->config->detach_timeout) {
4939 q = silc_calloc(1, sizeof(*q));
4941 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4942 silc_schedule_task_add(server->schedule, 0,
4943 silc_server_command_detach_timeout,
4944 q, server->config->detach_timeout * 60,
4945 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4948 /* Send reply to the sender */
4949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4953 silc_server_command_free(cmd);
4956 /* Server side of WATCH command. */
4958 SILC_SERVER_CMD_FUNC(watch)
4960 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4961 SilcServer server = cmd->server;
4962 char *add_nick, *del_nick;
4963 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
4965 unsigned char hash[16], *tmp;
4966 SilcClientEntry client;
4967 SilcClientID *client_id = NULL;
4969 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4971 if (server->server_type == SILC_SERVER && !server->standalone) {
4972 if (!cmd->pending) {
4973 /* Send the command to router */
4975 SilcUInt16 old_ident;
4977 old_ident = silc_command_get_ident(cmd->payload);
4978 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4979 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4981 silc_server_packet_send(server, server->router->connection,
4982 SILC_PACKET_COMMAND, cmd->packet->flags,
4983 tmpbuf->data, tmpbuf->len, TRUE);
4985 /* Reprocess this packet after received reply from router */
4986 silc_server_command_pending(server, SILC_COMMAND_WATCH,
4987 silc_command_get_ident(cmd->payload),
4988 silc_server_command_watch,
4989 silc_server_command_dup(cmd));
4990 cmd->pending = TRUE;
4991 silc_command_set_ident(cmd->payload, old_ident);
4992 silc_buffer_free(tmpbuf);
4993 } else if (context2) {
4994 /* Received reply from router, just send same data to the client. */
4995 SilcServerCommandReplyContext reply = context2;
4997 silc_command_get_status(reply->payload, &status, NULL);
4998 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5005 /* We are router and keep the watch list for local cell */
5007 /* Get the client ID */
5008 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5010 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5011 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5015 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5018 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5023 /* Get the client entry which must be in local list */
5024 client = silc_idlist_find_client_by_id(server->local_list,
5025 client_id, TRUE, NULL);
5027 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5028 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5034 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5035 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5036 if (!add_nick && !del_nick) {
5037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5038 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5043 if (add_nick && add_nick_len > 128)
5044 add_nick[128] = '\0';
5045 if (del_nick && del_nick_len > 128)
5046 del_nick[128] = '\0';
5048 memset(nick, 0, sizeof(nick));
5050 /* Add new nickname to be watched in our cell */
5052 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5053 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5054 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5058 /* Hash the nick, we have the hash saved, not nicks because we can
5059 do one to one mapping to the nick from Client ID hash this way. */
5060 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5061 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5063 /* Check whether this client is already watching this nickname */
5064 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5066 /* Nickname is alredy being watched for this client */
5067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5068 SILC_STATUS_ERR_NICKNAME_IN_USE,
5073 /* Get the nickname from the watcher list and use the same key in
5074 new entries as well. If key doesn't exist then create it. */
5075 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5076 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5078 /* Add the client to the watcher list with the specified nickname hash. */
5079 silc_hash_table_add(server->watcher_list, tmp, client);
5082 /* Delete nickname from watch list */
5084 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5086 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5090 /* Hash the nick, we have the hash saved, not nicks because we can
5091 do one to one mapping to the nick from Client ID hash this way. */
5092 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5093 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5095 /* Check that this client is watching for this nickname */
5096 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5097 client, (void **)&tmp)) {
5098 /* Nickname is alredy being watched for this client */
5099 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5100 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5104 /* Delete the nickname from the watcher list. */
5105 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5107 /* Now check whether there still exists entries with this key, if not
5108 then free the key to not leak memory. */
5109 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5113 /* Distribute the watch list to backup routers too */
5114 if (server->backup) {
5116 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5117 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5118 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5119 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5121 silc_buffer_free(tmpbuf);
5124 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5128 silc_free(client_id);
5129 silc_server_command_free(cmd);
5132 /* Server side of SILCOPER command. Client uses this comand to obtain router
5133 operator privileges to this router. */
5135 SILC_SERVER_CMD_FUNC(silcoper)
5137 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5138 SilcServer server = cmd->server;
5139 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5140 unsigned char *username, *auth;
5142 SilcServerConfigAdmin *admin;
5143 SilcIDListData idata = (SilcIDListData)client;
5144 bool result = FALSE;
5145 SilcPublicKey cached_key;
5147 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5149 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5152 if (server->server_type != SILC_ROUTER) {
5153 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5154 SILC_STATUS_ERR_AUTH_FAILED, 0);
5158 /* Get the username */
5159 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5161 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5162 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5167 /* Get the admin configuration */
5168 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5169 username, client->nickname);
5171 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5172 username, client->nickname);
5174 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5175 SILC_STATUS_ERR_AUTH_FAILED, 0);
5180 /* Get the authentication payload */
5181 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5184 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5189 /* Verify the authentication data. If both passphrase and public key
5190 is set then try both of them. */
5191 if (admin->passphrase)
5192 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5193 admin->passphrase, admin->passphrase_len,
5194 idata->hash, client->id, SILC_ID_CLIENT);
5195 if (!result && admin->publickeys) {
5196 cached_key = silc_server_get_public_key(server, admin->publickeys);
5199 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5200 cached_key, 0, idata->hash,
5201 client->id, SILC_ID_CLIENT);
5204 /* Authentication failed */
5205 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5206 SILC_STATUS_ERR_AUTH_FAILED, 0);
5210 /* Client is now router operator */
5211 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5213 /* Update statistics */
5214 if (client->connection)
5215 server->stat.my_router_ops++;
5216 if (server->server_type == SILC_ROUTER)
5217 server->stat.router_ops++;
5219 /* Send UMODE change to primary router */
5220 if (!server->standalone)
5221 silc_server_send_notify_umode(server, server->router->connection, TRUE,
5222 client->id, client->mode);
5224 /* Check if anyone is watching this nickname */
5225 if (server->server_type == SILC_ROUTER)
5226 silc_server_check_watcher_list(server, client, NULL,
5227 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5229 /* Send reply to the sender */
5230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5234 silc_server_command_free(cmd);
5237 /* Server side of command BAN. This is used to manage the ban list of the
5238 channel. To add clients and remove clients from the ban list. */
5240 SILC_SERVER_CMD_FUNC(ban)
5242 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5243 SilcServer server = cmd->server;
5244 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5246 SilcChannelEntry channel;
5247 SilcChannelClientEntry chl;
5248 SilcChannelID *channel_id = NULL;
5249 unsigned char *id, *add, *del;
5250 SilcUInt32 id_len, tmp_len;
5251 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5253 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5256 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5258 /* Get Channel ID */
5259 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5261 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5263 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5264 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5269 /* Get channel entry. The server must know about the channel since the
5270 client is expected to be on the channel. */
5271 channel = silc_idlist_find_channel_by_id(server->local_list,
5274 channel = silc_idlist_find_channel_by_id(server->global_list,
5277 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5278 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5284 /* Check whether this client is on the channel */
5285 if (!silc_server_client_on_channel(client, channel, &chl)) {
5286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5287 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5291 /* The client must be at least channel operator. */
5292 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5294 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5298 /* Get the new ban and add it to the ban list */
5299 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5301 if (!channel->ban_list)
5302 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5304 channel->ban_list = silc_realloc(channel->ban_list,
5305 sizeof(*channel->ban_list) *
5307 strlen(channel->ban_list) + 2));
5308 if (add[tmp_len - 1] == ',')
5309 add[tmp_len - 1] = '\0';
5311 strncat(channel->ban_list, add, tmp_len);
5312 strncat(channel->ban_list, ",", 1);
5315 /* Get the ban to be removed and remove it from the list */
5316 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5317 if (del && channel->ban_list) {
5318 char *start, *end, *n;
5320 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5321 silc_free(channel->ban_list);
5322 channel->ban_list = NULL;
5324 start = strstr(channel->ban_list, del);
5325 if (start && strlen(start) >= tmp_len) {
5326 end = start + tmp_len;
5327 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5328 strncat(n, channel->ban_list, start - channel->ban_list);
5329 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5331 silc_free(channel->ban_list);
5332 channel->ban_list = n;
5337 /* Send the BAN notify type to our primary router. */
5338 if (!server->standalone && (add || del))
5339 silc_server_send_notify_ban(server, server->router->connection,
5340 server->server_type == SILC_ROUTER ?
5341 TRUE : FALSE, channel, add, del);
5343 /* Send the reply back to the client */
5345 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5346 SILC_STATUS_OK, 0, ident, 2,
5348 3, channel->ban_list,
5350 strlen(channel->ban_list) -1 : 0);
5351 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5352 packet->data, packet->len, FALSE);
5354 silc_buffer_free(packet);
5357 silc_free(channel_id);
5358 silc_server_command_free(cmd);
5361 /* Server side command of LEAVE. Removes client from a channel. */
5363 SILC_SERVER_CMD_FUNC(leave)
5365 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5366 SilcServer server = cmd->server;
5367 SilcSocketConnection sock = cmd->sock;
5368 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5369 SilcChannelID *id = NULL;
5370 SilcChannelEntry channel;
5374 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5376 /* Get Channel ID */
5377 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5379 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5380 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5383 id = silc_id_payload_parse_id(tmp, len, NULL);
5385 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5386 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5390 /* Get channel entry */
5391 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5393 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5396 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5402 /* Check whether this client is on the channel */
5403 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5404 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5405 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5409 /* Notify routers that they should remove this client from their list
5410 of clients on the channel. Send LEAVE notify type. */
5411 if (!server->standalone)
5412 silc_server_send_notify_leave(server, server->router->connection,
5413 server->server_type == SILC_ROUTER ?
5414 TRUE : FALSE, channel, id_entry->id);
5416 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5417 SILC_STATUS_OK, 0, 2, tmp, len);
5419 /* Remove client from channel */
5420 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5422 /* If the channel does not exist anymore we won't send anything */
5425 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5426 /* Re-generate channel key */
5427 if (!silc_server_create_channel_key(server, channel, 0))
5430 /* Send the channel key */
5431 silc_server_send_channel_key(server, NULL, channel,
5432 server->server_type == SILC_ROUTER ?
5433 FALSE : !server->standalone);
5438 silc_server_command_free(cmd);
5441 /* Server side of command USERS. Resolves clients and their USERS currently
5442 joined on the requested channel. The list of Client ID's and their modes
5443 on the channel is sent back. */
5445 SILC_SERVER_CMD_FUNC(users)
5447 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5448 SilcServer server = cmd->server;
5449 SilcChannelEntry channel;
5450 SilcChannelID *id = NULL;
5451 SilcBuffer packet, idp;
5452 unsigned char *channel_id;
5453 SilcUInt32 channel_id_len;
5454 SilcBuffer client_id_list;
5455 SilcBuffer client_mode_list;
5456 unsigned char lc[4];
5457 SilcUInt32 list_count = 0;
5458 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5461 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5463 /* Get Channel ID */
5464 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5466 /* Get channel name */
5467 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5469 if (!channel_id && !channel_name) {
5470 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5471 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5476 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5478 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5479 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5484 /* If we are server and we don't know about this channel we will send
5485 the command to our router. If we know about the channel then we also
5486 have the list of users already. */
5488 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5490 channel = silc_idlist_find_channel_by_name(server->local_list,
5491 channel_name, NULL);
5493 if (!channel || (!server->standalone && (channel->disabled ||
5494 !channel->users_resolved))) {
5495 if (server->server_type != SILC_ROUTER && !server->standalone &&
5499 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5500 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5502 /* Send USERS command */
5503 silc_server_packet_send(server, server->router->connection,
5504 SILC_PACKET_COMMAND, cmd->packet->flags,
5505 tmpbuf->data, tmpbuf->len, TRUE);
5507 /* Reprocess this packet after received reply */
5508 silc_server_command_pending(server, SILC_COMMAND_USERS,
5509 silc_command_get_ident(cmd->payload),
5510 silc_server_command_users,
5511 silc_server_command_dup(cmd));
5512 cmd->pending = TRUE;
5513 silc_command_set_ident(cmd->payload, ident);
5514 silc_buffer_free(tmpbuf);
5519 /* Check the global list as well. */
5521 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5523 channel = silc_idlist_find_channel_by_name(server->global_list,
5524 channel_name, NULL);
5526 /* Channel really does not exist */
5527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5528 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5534 /* If the channel is private or secret do not send anything, unless the
5535 user requesting this command is on the channel or is server */
5536 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5537 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5538 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5541 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5546 /* Get the users list */
5547 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5548 &client_mode_list, &list_count)) {
5550 client_id_list = NULL;
5551 client_mode_list = NULL;
5555 SILC_PUT32_MSB(list_count, lc);
5558 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5559 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5560 SILC_STATUS_OK, 0, ident, 4,
5561 2, idp->data, idp->len,
5564 client_id_list->data : NULL,
5566 client_id_list->len : 0,
5567 5, client_mode_list ?
5568 client_mode_list->data : NULL,
5570 client_mode_list->len : 0);
5571 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5572 packet->data, packet->len, FALSE);
5574 silc_buffer_free(idp);
5575 silc_buffer_free(packet);
5577 silc_buffer_free(client_id_list);
5578 if (client_mode_list)
5579 silc_buffer_free(client_mode_list);
5583 silc_server_command_free(cmd);
5586 /* Server side of command GETKEY. This fetches the client's public key
5587 from the server where to the client is connected. */
5589 SILC_SERVER_CMD_FUNC(getkey)
5591 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5592 SilcServer server = cmd->server;
5594 SilcClientEntry client;
5595 SilcServerEntry server_entry;
5596 SilcClientID *client_id = NULL;
5597 SilcServerID *server_id = NULL;
5598 SilcIDPayload idp = NULL;
5599 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5600 unsigned char *tmp, *pkdata;
5601 SilcUInt32 tmp_len, pklen;
5602 SilcBuffer pk = NULL;
5604 SilcPublicKey public_key;
5606 SILC_LOG_DEBUG(("Start"));
5608 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5610 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5611 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5615 idp = silc_id_payload_parse(tmp, tmp_len);
5617 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5618 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5623 id_type = silc_id_payload_get_type(idp);
5624 if (id_type == SILC_ID_CLIENT) {
5625 client_id = silc_id_payload_get_id(idp);
5627 /* If the client is not found from local list there is no chance it
5628 would be locally connected client so send the command further. */
5629 client = silc_idlist_find_client_by_id(server->local_list,
5630 client_id, TRUE, NULL);
5632 client = silc_idlist_find_client_by_id(server->global_list,
5633 client_id, TRUE, NULL);
5635 if ((!client && !cmd->pending && !server->standalone) ||
5636 (client && !client->connection && !cmd->pending &&
5637 !(client->mode & SILC_UMODE_DETACHED)) ||
5638 (client && !client->data.public_key && !cmd->pending)) {
5640 SilcUInt16 old_ident;
5641 SilcSocketConnection dest_sock;
5643 dest_sock = silc_server_get_client_route(server, NULL, 0,
5644 client_id, NULL, NULL);
5648 old_ident = silc_command_get_ident(cmd->payload);
5649 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5650 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5652 silc_server_packet_send(server, dest_sock,
5653 SILC_PACKET_COMMAND, cmd->packet->flags,
5654 tmpbuf->data, tmpbuf->len, TRUE);
5656 /* Reprocess this packet after received reply from router */
5657 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5658 silc_command_get_ident(cmd->payload),
5659 silc_server_command_getkey,
5660 silc_server_command_dup(cmd));
5661 cmd->pending = TRUE;
5662 silc_command_set_ident(cmd->payload, old_ident);
5663 silc_buffer_free(tmpbuf);
5668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5669 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5674 /* The client is locally connected, just get the public key and
5675 send it back. If they key does not exist then do not send it,
5676 send just OK reply */
5677 public_key = client->data.public_key;
5682 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5683 pk = silc_buffer_alloc(4 + tmp_len);
5684 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5685 silc_buffer_format(pk,
5686 SILC_STR_UI_SHORT(tmp_len),
5687 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5688 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5694 } else if (id_type == SILC_ID_SERVER) {
5695 server_id = silc_id_payload_get_id(idp);
5697 /* If the server is not found from local list there is no chance it
5698 would be locally connected server so send the command further. */
5699 server_entry = silc_idlist_find_server_by_id(server->local_list,
5700 server_id, TRUE, NULL);
5702 server_entry = silc_idlist_find_server_by_id(server->global_list,
5703 server_id, TRUE, NULL);
5705 if (server_entry != server->id_entry &&
5706 ((!server_entry && !cmd->pending && !server->standalone) ||
5707 (server_entry && !server_entry->connection && !cmd->pending &&
5708 !server->standalone) ||
5709 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5710 !server->standalone))) {
5712 SilcUInt16 old_ident;
5714 old_ident = silc_command_get_ident(cmd->payload);
5715 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5716 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5718 silc_server_packet_send(server, server->router->connection,
5719 SILC_PACKET_COMMAND, cmd->packet->flags,
5720 tmpbuf->data, tmpbuf->len, TRUE);
5722 /* Reprocess this packet after received reply from router */
5723 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5724 silc_command_get_ident(cmd->payload),
5725 silc_server_command_getkey,
5726 silc_server_command_dup(cmd));
5727 cmd->pending = TRUE;
5728 silc_command_set_ident(cmd->payload, old_ident);
5729 silc_buffer_free(tmpbuf);
5733 if (!server_entry) {
5734 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5735 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5740 /* If they key does not exist then do not send it, send just OK reply */
5741 public_key = (!server_entry->data.public_key ?
5742 (server_entry == server->id_entry ? server->public_key :
5743 NULL) : server_entry->data.public_key);
5748 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5749 pk = silc_buffer_alloc(4 + tmp_len);
5750 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5751 silc_buffer_format(pk,
5752 SILC_STR_UI_SHORT(tmp_len),
5753 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5754 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5764 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5765 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5766 SILC_STATUS_OK, 0, ident,
5770 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5771 packet->data, packet->len, FALSE);
5772 silc_buffer_free(packet);
5775 silc_buffer_free(pk);
5779 silc_id_payload_free(idp);
5780 silc_free(client_id);
5781 silc_free(server_id);
5782 silc_server_command_free(cmd);
5786 /* Private range commands, specific to this implementation */
5788 /* Server side command of CONNECT. Connects us to the specified remote
5789 server or router. */
5791 SILC_SERVER_CMD_FUNC(connect)
5793 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5794 SilcServer server = cmd->server;
5795 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5796 unsigned char *tmp, *host;
5798 SilcUInt32 port = SILC_PORT;
5800 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5802 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5805 /* Check whether client has the permissions. */
5806 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5807 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5808 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5809 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5813 if (server->server_type == SILC_ROUTER &&
5814 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5816 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5820 /* Get the remote server */
5821 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5824 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5830 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5832 SILC_GET32_MSB(port, tmp);
5834 /* Create the connection. It is done with timeout and is async. */
5835 silc_server_create_connection(server, host, port);
5837 /* Send reply to the sender */
5838 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5842 silc_server_command_free(cmd);
5845 /* Server side command of CLOSE. Closes connection to a specified server. */
5847 SILC_SERVER_CMD_FUNC(close)
5849 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5850 SilcServer server = cmd->server;
5851 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5852 SilcServerEntry server_entry;
5853 SilcSocketConnection sock;
5856 unsigned char *name;
5857 SilcUInt32 port = SILC_PORT;
5859 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, 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_CLOSE,
5868 SILC_STATUS_ERR_NO_SERVER_PRIV,
5873 /* Get the remote server */
5874 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5876 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5877 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5883 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5885 SILC_GET32_MSB(port, tmp);
5887 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5888 name, port, FALSE, NULL);
5890 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5891 name, port, FALSE, NULL);
5892 if (!server_entry) {
5893 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5894 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5898 /* Send reply to the sender */
5899 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5902 /* Close the connection to the server */
5903 sock = (SilcSocketConnection)server_entry->connection;
5905 /* If we shutdown primary router connection manually then don't trigger
5906 any reconnect or backup router connections, by setting the router
5908 if (server->router == server_entry) {
5909 server->id_entry->router = NULL;
5910 server->router = NULL;
5911 server->standalone = TRUE;
5913 silc_server_free_sock_user_data(server, sock, NULL);
5914 silc_server_close_connection(server, sock);
5917 silc_server_command_free(cmd);
5920 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5921 active connections. */
5923 SILC_SERVER_CMD_FUNC(shutdown)
5925 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5926 SilcServer server = cmd->server;
5927 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5929 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5931 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5934 /* Check whether client has the permission. */
5935 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5936 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5937 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5938 SILC_STATUS_ERR_NO_SERVER_PRIV,
5943 /* Send reply to the sender */
5944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5947 /* Then, gracefully, or not, bring the server down. */
5948 silc_server_stop(server);
5952 silc_server_command_free(cmd);