5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2009 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "serverincludes.h"
22 #include "server_internal.h"
23 #include "command_reply.h"
25 /* All functions that call the COMMAND_CHECK_STATUS macros must have
26 out: and err: goto labels. */
28 #define COMMAND_CHECK_STATUS \
30 SILC_LOG_DEBUG(("Start")); \
31 if (!silc_command_get_status(cmd->payload, &status, &error)) { \
32 if (SILC_STATUS_IS_ERROR(status)) \
34 if (status == SILC_STATUS_LIST_END) \
40 /* Server command reply list. Not all commands have reply function as
41 they are never sent by server. More maybe added later if need appears. */
42 SilcServerCommandReply silc_command_reply_list[] =
44 SILC_SERVER_CMD_REPLY(whois, WHOIS),
45 SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
46 SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
47 SILC_SERVER_CMD_REPLY(info, INFO),
48 SILC_SERVER_CMD_REPLY(motd, MOTD),
49 SILC_SERVER_CMD_REPLY(join, JOIN),
50 SILC_SERVER_CMD_REPLY(stats, STATS),
51 SILC_SERVER_CMD_REPLY(users, USERS),
52 SILC_SERVER_CMD_REPLY(getkey, GETKEY),
53 SILC_SERVER_CMD_REPLY(list, LIST),
54 SILC_SERVER_CMD_REPLY(watch, WATCH),
55 SILC_SERVER_CMD_REPLY(ping, PING),
60 /* Process received command reply. */
62 void silc_server_command_reply_process(SilcServer server,
63 SilcPacketStream sock,
66 SilcIDListData idata = silc_packet_get_context(sock);
67 SilcServerCommandReply *cmd;
68 SilcServerCommandReplyContext ctx;
69 SilcCommandPayload payload;
72 SILC_LOG_DEBUG(("Start"));
74 /* Get command reply payload from packet */
75 payload = silc_command_payload_parse(buffer->data, silc_buffer_len(buffer));
77 /* Silently ignore bad reply packet */
78 SILC_LOG_DEBUG(("Bad command reply packet"));
82 /* Allocate command reply context. This must be free'd by the
83 command reply routine receiving it. */
84 ctx = silc_calloc(1, sizeof(*ctx));
87 ctx->payload = payload;
88 ctx->args = silc_command_get_args(ctx->payload);
89 ctx->ident = silc_command_get_ident(ctx->payload);
90 command = silc_command_get(ctx->payload);
91 silc_packet_stream_ref(sock);
93 /* Client is not allowed to send reply to all commands */
94 if (idata->conn_type == SILC_CONN_CLIENT &&
95 command != SILC_COMMAND_WHOIS) {
96 silc_server_command_reply_free(ctx);
100 /* Check for pending commands and mark to be exeucted */
102 silc_server_command_pending_check(server, command,
103 ctx->ident, &ctx->callbacks_count);
105 /* Execute command reply */
106 for (cmd = silc_command_reply_list; cmd->cb; cmd++)
107 if (cmd->cmd == command)
110 if (cmd == NULL || !cmd->cb) {
111 silc_server_command_reply_free(ctx);
118 /* Free command reply context and its internals. */
120 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
123 silc_command_payload_free(cmd->payload);
125 silc_packet_stream_unref(cmd->sock);
126 silc_free(cmd->callbacks);
132 silc_server_command_process_error(SilcServerCommandReplyContext cmd,
135 SilcServer server = cmd->server;
136 SilcIDListData idata = silc_packet_get_context(cmd->sock);
138 /* If we received notify for invalid ID we'll remove the ID if we
140 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
141 idata->conn_type == SILC_CONN_ROUTER) {
142 SilcClientEntry client;
144 if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id,
146 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
147 "the entry from cache"));
148 client = silc_idlist_find_client_by_id(server->global_list,
149 SILC_ID_GET_ID(id), FALSE, NULL);
153 silc_server_remove_from_channels(server, NULL, client, TRUE,
155 silc_dlist_del(server->expired_clients, client);
156 silc_idlist_del_data(client);
157 silc_idlist_del_client(server->global_list, client);
162 /* Caches the received WHOIS information. */
165 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
167 SilcServer server = cmd->server;
168 unsigned char *id_data, *umodes;
169 char *nickname, *username, *realname, *tmp;
170 unsigned char *fingerprint;
172 SilcClientEntry client;
174 char nick[128 + 1], servername[256 + 1], uname[128 + 1];
175 SilcUInt32 mode = 0, len, len2, id_len, flen;
176 const char *hostname, *ip;
178 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
179 NULL, &hostname, &ip, NULL);
181 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
182 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
183 username = silc_argument_get_arg_type(cmd->args, 4, &len);
184 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
185 if (!id_data || !nickname || !username || !realname)
188 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
190 SILC_GET32_MSB(mode, tmp);
192 if (!silc_id_payload_parse_id(id_data, id_len, &id))
195 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
197 /* Check if we have this client cached already. */
199 client = silc_idlist_find_client_by_id(server->local_list,
203 client = silc_idlist_find_client_by_id(server->global_list,
210 /* If router did not find such Client ID in its lists then this must
211 be bogus client or some router in the net is buggy. */
212 if (server->server_type != SILC_SERVER)
215 /* Take hostname out of nick string if it includes it. */
216 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
219 /* We don't have that client anywhere, add it. The client is added
220 to global list since server didn't have it in the lists so it must be
221 global. This will check for valid nickname and username strings. */
222 client = silc_idlist_add_client(server->global_list,
223 strdup(nick), username,
225 silc_id_dup(SILC_ID_GET_ID(id),
227 silc_packet_get_context(cmd->sock),
230 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
234 client->data.status |=
235 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
236 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
238 client->servername = servername[0] ? strdup(servername) : NULL;
240 SILC_LOG_DEBUG(("stat.clients %d->%d", server->stat.clients,
241 server->stat.clients + 1));
242 server->stat.clients++;
244 /* We have the client already, update the data */
246 SILC_LOG_DEBUG(("Updating client data"));
249 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
251 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
254 SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOIS reply "
256 hostname ? hostname : "", nick));
261 silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
262 if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128)) {
263 SILC_LOG_ERROR(("Malformed username '%s' received in WHOIS reply "
265 hostname ? hostname : "", tmp));
270 silc_idcache_update_by_context(global ? server->global_list->clients :
271 server->local_list->clients, client, NULL,
274 silc_free(client->nickname);
275 silc_free(client->username);
276 silc_free(client->userinfo);
277 silc_free(client->servername);
279 client->nickname = strdup(nick);
280 client->username = strdup(username);
281 client->userinfo = strdup(realname);
282 client->servername = servername[0] ? strdup(servername) : NULL;
284 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
285 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
288 /* Save channel list if it was sent to us */
289 if (server->server_type == SILC_SERVER) {
290 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
291 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
293 SilcBufferStruct channels_buf, umodes_buf;
294 silc_buffer_set(&channels_buf, tmp, len);
295 silc_buffer_set(&umodes_buf, umodes, len2);
296 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
299 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
303 if (fingerprint && flen == sizeof(client->data.fingerprint))
304 memcpy(client->data.fingerprint, fingerprint, flen);
306 /* Take Requested Attributes if set. */
307 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
309 silc_free(client->attrs);
310 client->attrs = silc_memdup(tmp, len);
311 client->attrs_len = len;
313 /* Try to take public key from attributes if present and we don't have
314 the key already. Do this only on normal server. Routers do GETKEY
315 for all clients anyway. */
316 if (server->server_type != SILC_ROUTER && !client->data.public_key) {
317 SilcAttributePayload attr;
318 SilcAttributeObjPk pk;
319 unsigned char f[SILC_HASH_MAXLEN];
320 SilcDList attrs = silc_attribute_payload_parse(tmp, len);
322 SILC_LOG_DEBUG(("Take client public key from attributes"));
325 silc_dlist_start(attrs);
326 while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
327 if (silc_attribute_get_attribute(attr) ==
328 SILC_ATTRIBUTE_USER_PUBLIC_KEY) {
330 if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
333 /* Take only SILC public keys */
334 if (strcmp(pk.type, "silc-rsa")) {
340 /* Verify that the server provided fingerprint matches the key */
341 silc_hash_make(server->sha1hash, pk.data, pk.data_len, f);
342 if (memcmp(f, client->data.fingerprint, sizeof(f))) {
348 /* Save the public key. */
349 if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC,
350 pk.data, pk.data_len,
351 &client->data.public_key)) {
357 SILC_LOG_DEBUG(("Saved client public key from attributes"));
359 /* Add client's public key to repository */
360 if (!silc_server_get_public_key_by_client(server, client, NULL))
361 silc_skr_add_public_key_simple(server->repository,
362 client->data.public_key,
363 SILC_SKR_USAGE_IDENTIFICATION,
372 silc_attribute_payload_list_free(attrs);
380 /* Handle requested attributes reply in WHOIS from client */
383 silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd)
387 SilcClientEntry client = silc_packet_get_context(cmd->sock);
392 /* Take Requested Attributes if set. */
393 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
395 silc_free(client->attrs);
396 client->attrs = silc_memdup(tmp, len);
397 client->attrs_len = len;
400 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
405 /* Reiceved reply for WHOIS command. We sent the whois request to our
406 primary router, if we are normal server, and thus has now received reply
407 to the command. We will figure out what client originally sent us the
408 command and will send the reply to it. If we are router we will figure
409 out who server sent us the command and send reply to that one. */
411 SILC_SERVER_CMD_REPLY_FUNC(whois)
413 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
414 SilcIDListData idata = silc_packet_get_context(cmd->sock);
415 SilcStatus status, error;
417 COMMAND_CHECK_STATUS;
419 if (idata->conn_type != SILC_CONN_CLIENT) {
420 if (!silc_server_command_reply_whois_save(cmd))
423 if (!silc_server_command_reply_whois_save_client(cmd))
427 /* Pending callbacks are not executed if this was an list entry */
428 if (status != SILC_STATUS_OK &&
429 status != SILC_STATUS_LIST_END) {
430 silc_server_command_reply_free(cmd);
435 silc_server_command_process_error(cmd, error);
436 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
437 silc_server_command_reply_free(cmd);
441 silc_server_command_process_error(cmd, error);
442 silc_server_command_reply_free(cmd);
445 /* Caches the received WHOWAS information for a short period of time. */
448 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
450 SilcServer server = cmd->server;
451 SilcUInt32 len, id_len;
452 unsigned char *id_data;
453 char *nickname, *username, *realname;
455 SilcClientEntry client;
456 SilcIDCacheEntry cache = NULL;
457 char nick[128 + 1], servername[256 + 1], uname[128 + 1];
459 const char *hostname, *ip;
461 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
462 NULL, &hostname, &ip, NULL);
464 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
465 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
466 username = silc_argument_get_arg_type(cmd->args, 4, &len);
467 if (!id_data || !nickname || !username)
470 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
472 if (!silc_id_payload_parse_id(id_data, id_len, &id))
475 /* Check if we have this client cached already. */
477 client = silc_idlist_find_client_by_id(server->local_list,
481 client = silc_idlist_find_client_by_id(server->global_list,
488 /* If router did not find such Client ID in its lists then this must
489 be bogus client or some router in the net is buggy. */
490 if (server->server_type != SILC_SERVER)
493 /* Take hostname out of nick string if it includes it. */
494 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
497 /* We don't have that client anywhere, add it. The client is added
498 to global list since server didn't have it in the lists so it must be
500 client = silc_idlist_add_client(server->global_list,
501 strdup(nick), username,
503 silc_id_dup(SILC_ID_GET_ID(id),
505 silc_packet_get_context(cmd->sock), NULL);
507 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
511 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
512 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
513 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
514 client->servername = servername[0] ? strdup(servername) : NULL;
516 /* We have the client already, update the data */
519 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
521 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
524 SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOWAS reply "
526 nick, hostname ? hostname : ""));
531 silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
532 if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128))
535 silc_free(client->nickname);
536 silc_free(client->username);
537 silc_free(client->servername);
539 client->nickname = strdup(nick);
540 client->username = strdup(username);
541 client->servername = servername[0] ? strdup(servername) : NULL;
542 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
543 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
544 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
546 /* Update cache entry */
547 silc_idcache_update_by_context(global ? server->global_list->clients :
548 server->local_list->clients, client, NULL,
552 /* If client is global and is not on any channel then add that we'll
553 expire the entry after a while. */
555 client = silc_idlist_find_client_by_id(server->global_list, client->id,
557 if (client && !silc_hash_table_count(client->channels)) {
558 client->data.created = silc_time();
559 silc_dlist_del(server->expired_clients, client);
560 silc_dlist_add(server->expired_clients, client);
567 /* Received reply for WHOWAS command. Cache the client information only for
568 a short period of time. */
570 SILC_SERVER_CMD_REPLY_FUNC(whowas)
572 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
573 SilcStatus status, error;
575 COMMAND_CHECK_STATUS;
577 if (!silc_server_command_reply_whowas_save(cmd))
580 /* Pending callbacks are not executed if this was an list entry */
581 if (status != SILC_STATUS_OK &&
582 status != SILC_STATUS_LIST_END) {
583 silc_server_command_reply_free(cmd);
588 silc_server_command_process_error(cmd, error);
589 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
590 silc_server_command_reply_free(cmd);
594 silc_server_command_process_error(cmd, error);
595 silc_server_command_reply_free(cmd);
598 /* Caches the received IDENTIFY information. */
601 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
603 SilcServer server = cmd->server;
604 SilcUInt32 len, id_len;
605 unsigned char *id_data;
607 SilcClientID client_id;
608 SilcServerID server_id;
609 SilcChannelID channel_id;
610 SilcClientEntry client;
611 SilcServerEntry server_entry;
612 SilcChannelEntry channel;
615 SilcIDPayload idp = NULL;
618 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
621 idp = silc_id_payload_parse(id_data, id_len);
625 memset(nick, 0, sizeof(nick));
627 name = silc_argument_get_arg_type(cmd->args, 3, &len);
628 info = silc_argument_get_arg_type(cmd->args, 4, &len);
630 id_type = silc_id_payload_get_type(idp);
634 if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
637 SILC_LOG_DEBUG(("Received client information"));
639 client = silc_idlist_find_client_by_id(server->local_list,
640 &client_id, FALSE, NULL);
642 client = silc_idlist_find_client_by_id(server->global_list, &client_id,
647 /* If router did not find such Client ID in its lists then this must
648 be bogus client or some router in the net is buggy. */
649 if (server->server_type != SILC_SERVER)
654 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
656 /* We don't have that client anywhere, add it. The client is added
657 to global list since server didn't have it in the lists so it must be
659 client = silc_idlist_add_client(server->global_list,
660 nick[0] ? strdup(nick) : NULL,
661 info ? strdup(info) : NULL, NULL,
662 silc_id_dup(&client_id, SILC_ID_CLIENT),
663 silc_packet_get_context(cmd->sock),
666 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
670 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
671 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
672 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
674 SILC_LOG_DEBUG(("stat.clients %d->%d", server->stat.clients,
675 server->stat.clients + 1));
676 server->stat.clients++;
678 /* We have the client already, update the data */
680 SILC_LOG_DEBUG(("Updating client data"));
684 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
687 name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
690 SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY "
695 silc_free(client->nickname);
696 client->nickname = strdup(nick);
698 /* Update the context */
699 silc_idcache_update_by_context(global ? server->global_list->clients :
700 server->local_list->clients, client,
705 silc_free(client->username);
706 client->username = strdup(info);
709 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
710 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
719 if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
722 SILC_LOG_DEBUG(("Received server information"));
724 server_entry = silc_idlist_find_server_by_id(server->local_list,
725 &server_id, FALSE, NULL);
727 server_entry = silc_idlist_find_server_by_id(server->global_list,
728 &server_id, FALSE, NULL);
730 /* If router did not find such Server ID in its lists then this must
731 be bogus server or some router in the net is buggy. */
732 if (server->server_type != SILC_SERVER)
735 /* We don't have that server anywhere, add it. */
736 server_entry = silc_idlist_add_server(server->global_list,
738 silc_id_dup(&server_id,
741 SILC_PRIMARY_ROUTE(server));
745 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
746 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
747 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
752 case SILC_ID_CHANNEL:
756 if (!silc_id_payload_get_id(idp, &channel_id, sizeof(channel_id)))
759 SILC_LOG_DEBUG(("Received channel information"));
761 /* Check channel name */
762 info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
767 channel = silc_idlist_find_channel_by_name(server->local_list,
770 channel = silc_idlist_find_channel_by_name(server->global_list,
773 /* If router did not find such Channel ID in its lists then this must
774 be bogus channel or some router in the net is buggy. */
775 if (server->server_type != SILC_SERVER) {
780 /* We don't have that channel anywhere, add it. */
781 channel = silc_idlist_add_channel(server->global_list, strdup(name),
782 SILC_CHANNEL_MODE_NONE,
783 silc_id_dup(&channel_id,
785 server->router, NULL, NULL, 0);
796 silc_id_payload_free(idp);
800 silc_id_payload_free(idp);
804 /* Received reply for forwarded IDENTIFY command. We have received the
805 requested identify information now and we will cache it. After this we
806 will call the pending command so that the requestee gets the information
809 SILC_SERVER_CMD_REPLY_FUNC(identify)
811 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
812 SilcStatus status, error;
814 COMMAND_CHECK_STATUS;
816 if (!silc_server_command_reply_identify_save(cmd))
819 /* Pending callbacks are not executed if this was an list entry */
820 if (status != SILC_STATUS_OK &&
821 status != SILC_STATUS_LIST_END) {
822 silc_server_command_reply_free(cmd);
827 silc_server_command_process_error(cmd, error);
828 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
829 silc_server_command_reply_free(cmd);
833 silc_server_command_process_error(cmd, error);
834 silc_server_command_reply_free(cmd);
837 /* Received reply fro INFO command. Cache the server and its information */
839 SILC_SERVER_CMD_REPLY_FUNC(info)
841 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
842 SilcServer server = cmd->server;
843 SilcStatus status, error;
844 SilcServerEntry entry;
847 unsigned char *tmp, *name;
849 COMMAND_CHECK_STATUS;
852 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
856 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
860 entry = silc_idlist_find_server_by_id(server->local_list,
864 entry = silc_idlist_find_server_by_id(server->global_list,
868 /* Add the server to global list */
869 entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
870 silc_id_dup(SILC_ID_GET_ID(id),
872 silc_packet_get_context(cmd->sock),
877 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
881 /* Get the info string */
882 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
886 entry->server_info = tmp ? strdup(tmp) : NULL;
889 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
891 silc_server_command_reply_free(cmd);
894 /* Received reply fro MOTD command. */
896 SILC_SERVER_CMD_REPLY_FUNC(motd)
898 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
899 SilcServer server = cmd->server;
900 SilcStatus status, error;
901 SilcServerEntry entry = NULL;
906 COMMAND_CHECK_STATUS;
909 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
912 entry = silc_idlist_find_server_by_id(server->local_list,
916 entry = silc_idlist_find_server_by_id(server->global_list,
922 /* If router did not find such Server ID in its lists then this must
923 be bogus client or some router in the net is buggy. */
924 if (server->server_type != SILC_SERVER)
928 cmd->server->stat.commands_sent++;
930 /* entry isn't known so we IDENTIFY it. otherwise the
931 silc_server_command_motd won't know about it and tell
932 the client that there is no such server */
933 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
934 buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
935 ++server->cmd_ident, 5,
936 1, NULL, 0, 2, NULL, 0,
937 3, NULL, 0, 4, NULL, 0,
939 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
940 SILC_PACKET_COMMAND, 0, buffer->data,
941 silc_buffer_len(buffer));
942 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
944 silc_server_command_reply_motd,
946 silc_buffer_free(buffer);
952 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
959 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
961 silc_server_command_reply_free(cmd);
967 /* Received reply for forwarded JOIN command. Router has created or joined
968 the client to the channel. We save some channel information locally
971 SILC_SERVER_CMD_REPLY_FUNC(join)
973 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
974 SilcServer server = cmd->server;
975 SilcIDCacheEntry cache = NULL;
976 SilcStatus status, error;
978 SilcChannelEntry entry;
979 SilcHmac hmac = NULL;
980 SilcUInt32 len, list_count;
981 char *channel_name, *channel_namec = NULL, *tmp;
982 SilcUInt32 mode, created;
983 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
984 SilcPublicKey founder_key = NULL;
986 COMMAND_CHECK_STATUS;
988 /* Get channel name */
989 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
994 if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id, NULL))
998 if (!silc_argument_get_decoded(cmd->args, 4, SILC_ARGUMENT_ID, &id2, NULL))
1002 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1005 SILC_GET32_MSB(mode, tmp);
1007 /* Get created boolean value */
1008 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1011 SILC_GET32_MSB(created, tmp);
1012 if (created != 0 && created != 1)
1015 /* Get channel key */
1016 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
1018 keyp = silc_buffer_alloc(len);
1019 silc_buffer_pull_tail(keyp, silc_buffer_truelen(keyp));
1020 silc_buffer_put(keyp, tmp, len);
1024 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1026 if (!silc_hmac_alloc(tmp, NULL, &hmac))
1030 /* Get the list count */
1031 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1034 SILC_GET32_MSB(list_count, tmp);
1036 /* Get Client ID list */
1037 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1041 client_id_list = silc_buffer_alloc(len);
1042 silc_buffer_pull_tail(client_id_list, len);
1043 silc_buffer_put(client_id_list, tmp, len);
1045 /* Get client mode list */
1046 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1050 client_mode_list = silc_buffer_alloc(len);
1051 silc_buffer_pull_tail(client_mode_list, len);
1052 silc_buffer_put(client_mode_list, tmp, len);
1054 /* Get founder key */
1055 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1057 silc_public_key_payload_decode(tmp, len, &founder_key);
1059 /* See whether we already have the channel. */
1060 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
1061 SILC_STRING_UTF8, 256, NULL);
1064 entry = silc_idlist_find_channel_by_name(server->local_list,
1065 channel_namec, &cache);
1067 /* Add new channel */
1069 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1070 (created == 0 ? "existing" : "created"), channel_name,
1071 silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL)));
1073 /* If the channel is found from global list we must move it to the
1075 entry = silc_idlist_find_channel_by_name(server->global_list,
1076 channel_namec, &cache);
1078 silc_idlist_del_channel(server->global_list, entry);
1080 /* Add the channel to our local list. */
1081 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1082 SILC_CHANNEL_MODE_NONE,
1083 silc_id_dup(SILC_ID_GET_ID(id),
1085 server->router, NULL, NULL, hmac);
1090 server->stat.my_channels++;
1091 server->stat.channels++;
1093 /* The entry exists. */
1095 /* If ID has changed, then update it to the cache too. */
1096 if (!SILC_ID_CHANNEL_COMPARE(entry->id, SILC_ID_GET_ID(id)))
1097 silc_idlist_replace_channel_id(server->local_list, entry->id,
1098 SILC_ID_GET_ID(id));
1100 entry->disabled = FALSE;
1102 /* Remove the founder auth data if the mode is not set but we have
1103 them in the entry */
1104 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1105 silc_pkcs_public_key_free(entry->founder_key);
1106 entry->founder_key = NULL;
1111 if (entry->founder_key)
1112 silc_pkcs_public_key_free(entry->founder_key);
1113 entry->founder_key = founder_key;
1117 if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1118 silc_free(entry->hmac_name);
1119 entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1122 /* Get the ban list */
1123 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1124 if (tmp && len > 2) {
1125 SilcArgumentPayload iargs;
1127 SILC_GET16_MSB(iargc, tmp);
1128 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1130 /* Delete old ban list */
1131 if (entry->ban_list)
1132 silc_hash_table_free(entry->ban_list);
1134 silc_hash_table_alloc(0, silc_hash_ptr,
1136 silc_server_inviteban_destruct, entry, TRUE);
1138 /* Add new ban list */
1139 silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1140 silc_argument_payload_free(iargs);
1144 /* Get the invite list */
1145 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1146 if (tmp && len > 2) {
1147 SilcArgumentPayload iargs;
1149 SILC_GET16_MSB(iargc, tmp);
1150 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1152 /* Delete old invite list */
1153 if (entry->invite_list)
1154 silc_hash_table_free(entry->invite_list);
1155 entry->invite_list =
1156 silc_hash_table_alloc(0, silc_hash_ptr,
1158 silc_server_inviteban_destruct, entry, TRUE);
1160 /* Add new invite list */
1161 silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1162 silc_argument_payload_free(iargs);
1167 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1169 silc_free(entry->topic);
1170 entry->topic = strdup(tmp);
1173 /* Get channel public key list */
1174 tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1175 if (tmp && server->server_type != SILC_ROUTER)
1176 silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1178 /* The the user limit */
1179 tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1180 if (tmp && len == 4)
1181 SILC_GET32_MSB(entry->user_limit, tmp);
1183 /* If channel was not created we know there is global users on the
1185 entry->global_users = (created == 0 ? TRUE : FALSE);
1187 /* If channel was just created the mask must be zero */
1188 if (!entry->global_users && mode)
1191 /* Save channel mode */
1194 /* Save channel key */
1196 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1197 silc_server_save_channel_key(server, keyp, entry);
1198 silc_buffer_free(keyp);
1201 /* Save the users to the channel */
1202 silc_server_save_users_on_channel(server, cmd->sock, entry,
1203 SILC_ID_GET_ID(id2), client_id_list,
1204 client_mode_list, list_count);
1205 entry->users_resolved = TRUE;
1208 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1210 silc_free(channel_namec);
1212 silc_hmac_free(hmac);
1213 silc_server_command_reply_free(cmd);
1216 silc_pkcs_public_key_free(founder_key);
1218 silc_buffer_free(client_id_list);
1219 if (client_mode_list)
1220 silc_buffer_free(client_mode_list);
1223 /* Received reply to STATS command. */
1225 SILC_SERVER_CMD_REPLY_FUNC(stats)
1227 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1228 SilcServer server = cmd->server;
1229 SilcStatus status, error;
1232 SilcBufferStruct buf;
1234 COMMAND_CHECK_STATUS;
1236 /* Get statistics structure */
1237 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1238 if (server->server_type != SILC_ROUTER && tmp) {
1239 silc_buffer_set(&buf, tmp, tmp_len);
1240 silc_buffer_unformat(&buf,
1241 SILC_STR_UI_INT(NULL),
1242 SILC_STR_UI_INT(NULL),
1243 SILC_STR_UI_INT(NULL),
1244 SILC_STR_UI_INT(NULL),
1245 SILC_STR_UI_INT(NULL),
1246 SILC_STR_UI_INT(NULL),
1247 SILC_STR_UI_INT(&server->stat.cell_clients),
1248 SILC_STR_UI_INT(&server->stat.cell_channels),
1249 SILC_STR_UI_INT(&server->stat.cell_servers),
1250 SILC_STR_UI_INT(&server->stat.clients),
1251 SILC_STR_UI_INT(&server->stat.channels),
1252 SILC_STR_UI_INT(&server->stat.servers),
1253 SILC_STR_UI_INT(&server->stat.routers),
1254 SILC_STR_UI_INT(&server->stat.server_ops),
1255 SILC_STR_UI_INT(&server->stat.router_ops),
1259 SILC_LOG_DEBUG(("stat.clients = %d", server->stat.clients));
1262 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1264 silc_server_command_reply_free(cmd);
1267 SILC_SERVER_CMD_REPLY_FUNC(users)
1269 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1270 SilcServer server = cmd->server;
1271 SilcStatus status, error;
1272 SilcChannelEntry channel;
1274 SilcBuffer client_id_list;
1275 SilcBuffer client_mode_list;
1278 SilcUInt32 list_count;
1280 COMMAND_CHECK_STATUS;
1282 /* Get channel ID */
1283 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1286 /* Get channel entry */
1287 channel = silc_idlist_find_channel_by_id(server->local_list,
1288 SILC_ID_GET_ID(id), NULL);
1290 channel = silc_idlist_find_channel_by_id(server->global_list,
1291 SILC_ID_GET_ID(id), NULL);
1295 if (cmd->pending || server->server_type != SILC_SERVER)
1298 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1299 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1300 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1301 1, 5, idp->data, silc_buffer_len(idp));
1302 silc_buffer_free(idp);
1304 /* Register pending command callback. After we've received the channel
1305 information we will reprocess this command reply by re-calling this
1306 USERS command reply callback. */
1307 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1309 silc_server_command_reply_users, cmd);
1311 cmd->pending = TRUE;
1316 /* Get the list count */
1317 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1320 SILC_GET32_MSB(list_count, tmp);
1322 /* Get Client ID list */
1323 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1327 client_id_list = silc_buffer_alloc(tmp_len);
1328 silc_buffer_pull_tail(client_id_list, tmp_len);
1329 silc_buffer_put(client_id_list, tmp, tmp_len);
1331 /* Get client mode list */
1332 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1336 client_mode_list = silc_buffer_alloc(tmp_len);
1337 silc_buffer_pull_tail(client_mode_list, tmp_len);
1338 silc_buffer_put(client_mode_list, tmp, tmp_len);
1340 /* Save the users to the channel */
1341 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1342 client_id_list, client_mode_list,
1345 channel->global_users = silc_server_channel_has_global(channel);
1346 channel->users_resolved = TRUE;
1348 silc_buffer_free(client_id_list);
1349 silc_buffer_free(client_mode_list);
1352 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1354 silc_server_command_reply_free(cmd);
1357 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1359 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1360 SilcServer server = cmd->server;
1361 SilcStatus status, error;
1362 SilcClientEntry client = NULL;
1363 SilcServerEntry server_entry = NULL;
1364 SilcClientID client_id;
1365 SilcServerID server_id;
1368 SilcIDPayload idp = NULL;
1370 SilcPublicKey public_key = NULL;
1372 COMMAND_CHECK_STATUS;
1374 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1377 idp = silc_id_payload_parse(tmp, len);
1381 /* Get the public key payload */
1382 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1386 /* Decode the public key payload */
1387 if (!silc_public_key_payload_decode(tmp, len, &public_key))
1390 id_type = silc_id_payload_get_type(idp);
1391 if (id_type == SILC_ID_CLIENT) {
1392 silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
1394 client = silc_idlist_find_client_by_id(server->local_list, &client_id,
1397 client = silc_idlist_find_client_by_id(server->global_list,
1398 &client_id, TRUE, NULL);
1403 if (!client->data.public_key) {
1404 /* Add client's public key to repository */
1405 if (!silc_server_get_public_key_by_client(server, client, NULL))
1406 silc_skr_add_public_key_simple(server->repository,
1408 SILC_SKR_USAGE_IDENTIFICATION,
1410 client->data.public_key = public_key;
1413 } else if (id_type == SILC_ID_SERVER) {
1414 silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
1416 server_entry = silc_idlist_find_server_by_id(server->local_list,
1417 &server_id, TRUE, NULL);
1418 if (!server_entry) {
1419 server_entry = silc_idlist_find_server_by_id(server->global_list,
1420 &server_id, TRUE, NULL);
1425 server_entry->data.public_key = public_key;
1432 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1434 silc_id_payload_free(idp);
1436 silc_pkcs_public_key_free(public_key);
1438 silc_server_command_reply_free(cmd);
1441 SILC_SERVER_CMD_REPLY_FUNC(list)
1443 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1444 SilcServer server = cmd->server;
1445 SilcStatus status, error;
1447 SilcChannelEntry channel;
1448 SilcIDCacheEntry cache;
1449 unsigned char *tmp, *name, *namec = NULL, *topic;
1450 SilcUInt32 usercount = 0;
1452 COMMAND_CHECK_STATUS;
1454 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1457 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1458 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1459 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1461 SILC_GET32_MSB(usercount, tmp);
1463 namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
1468 /* Add the channel entry if we do not have it already */
1469 channel = silc_idlist_find_channel_by_name(server->local_list,
1472 channel = silc_idlist_find_channel_by_name(server->global_list,
1475 /* If router did not find such channel in its lists then this must
1476 be bogus channel or some router in the net is buggy. */
1477 if (server->server_type != SILC_SERVER)
1480 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1481 SILC_CHANNEL_MODE_NONE,
1482 silc_id_dup(SILC_ID_GET_ID(id),
1484 server->router, NULL, NULL, NULL);
1489 channel->user_count = usercount;
1492 silc_free(channel->topic);
1493 channel->topic = strdup(topic);
1496 /* Pending callbacks are not executed if this was an list entry */
1497 if (status != SILC_STATUS_OK &&
1498 status != SILC_STATUS_LIST_END) {
1499 silc_server_command_reply_free(cmd);
1504 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1507 silc_server_command_reply_free(cmd);
1510 SILC_SERVER_CMD_REPLY_FUNC(watch)
1512 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1513 SilcStatus status, error;
1515 COMMAND_CHECK_STATUS;
1518 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1520 silc_server_command_reply_free(cmd);
1523 SILC_SERVER_CMD_REPLY_FUNC(ping)
1525 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1526 SilcStatus status, error;
1528 COMMAND_CHECK_STATUS;
1531 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1533 silc_server_command_reply_free(cmd);