5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 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 SilcSocketConnection sock,
66 SilcServerCommandReply *cmd;
67 SilcServerCommandReplyContext ctx;
68 SilcCommandPayload payload;
71 SILC_LOG_DEBUG(("Start"));
73 /* Get command reply payload from packet */
74 payload = silc_command_payload_parse(buffer->data, buffer->len);
76 /* Silently ignore bad reply packet */
77 SILC_LOG_DEBUG(("Bad command reply packet"));
81 /* Allocate command reply context. This must be free'd by the
82 command reply routine receiving it. */
83 ctx = silc_calloc(1, sizeof(*ctx));
85 ctx->sock = silc_socket_dup(sock);
86 ctx->payload = payload;
87 ctx->args = silc_command_get_args(ctx->payload);
88 ctx->ident = silc_command_get_ident(ctx->payload);
89 command = silc_command_get(ctx->payload);
91 /* Client is not allowed to send reply to all commands */
92 if (sock->type == SILC_SOCKET_TYPE_CLIENT &&
93 command != SILC_COMMAND_WHOIS) {
94 silc_server_command_reply_free(ctx);
98 /* Check for pending commands and mark to be exeucted */
100 silc_server_command_pending_check(server, command,
101 ctx->ident, &ctx->callbacks_count);
103 /* Execute command reply */
104 for (cmd = silc_command_reply_list; cmd->cb; cmd++)
105 if (cmd->cmd == command)
108 if (cmd == NULL || !cmd->cb) {
109 silc_server_command_reply_free(ctx);
116 /* Free command reply context and its internals. */
118 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
121 silc_command_payload_free(cmd->payload);
123 silc_socket_free(cmd->sock); /* Decrease the reference counter */
124 silc_free(cmd->callbacks);
130 silc_server_command_process_error(SilcServerCommandReplyContext cmd,
133 SilcServer server = cmd->server;
135 /* If we received notify for invalid ID we'll remove the ID if we
137 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
138 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
139 SilcClientEntry client;
141 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
143 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
145 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
146 "the entry from cache"));
147 client = silc_idlist_find_client_by_id(server->global_list,
148 client_id, FALSE, NULL);
151 if (client->data.public_key)
152 silc_hash_table_del_by_context(server->pk_hash,
153 client->data.public_key,
156 silc_server_remove_from_channels(server, NULL, client, TRUE,
158 silc_idlist_del_data(client);
159 silc_idlist_del_client(server->global_list, client);
161 silc_free(client_id);
167 /* Caches the received WHOIS information. */
170 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
172 SilcServer server = cmd->server;
173 unsigned char *tmp, *id_data, *umodes;
174 char *nickname, *username, *realname, *servername = NULL;
175 unsigned char *fingerprint;
176 SilcClientID *client_id;
177 SilcClientEntry client;
178 SilcIDCacheEntry cache = NULL;
181 SilcUInt32 mode = 0, len, len2, id_len, flen;
183 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
184 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
185 username = silc_argument_get_arg_type(cmd->args, 4, &len);
186 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
187 if (!id_data || !nickname || !username || !realname)
190 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
192 SILC_GET32_MSB(mode, tmp);
194 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
198 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
200 /* Check for valid username */
201 username = silc_identifier_check(username, strlen(username),
202 SILC_STRING_UTF8, 128, NULL);
204 SILC_LOG_ERROR(("Malformed username received in WHOIS reply"));
208 /* Check if we have this client cached already. */
210 client = silc_idlist_find_client_by_id(server->local_list, client_id,
213 client = silc_idlist_find_client_by_id(server->global_list, client_id,
219 /* If router did not find such Client ID in its lists then this must
220 be bogus client or some router in the net is buggy. */
221 if (server->server_type != SILC_SERVER) {
226 /* Take hostname out of nick string if it includes it. */
227 silc_parse_userfqdn(nickname, &nick, &servername);
230 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
233 SILC_LOG_ERROR(("Malformed nickname received in WHOIS reply"));
240 /* We don't have that client anywhere, add it. The client is added
241 to global list since server didn't have it in the lists so it must be
243 client = silc_idlist_add_client(server->global_list, nick, username,
244 strdup(realname), client_id,
245 cmd->sock->user_data, NULL, 0);
247 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
253 client->data.status |=
254 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
255 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
257 client->servername = servername;
259 /* We have the client already, update the data */
261 SILC_LOG_DEBUG(("Updating client data"));
263 /* Take hostname out of nick string if it includes it. */
264 silc_parse_userfqdn(nickname, &nick, &servername);
267 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
270 SILC_LOG_ERROR(("Malformed nickname received in WHOIS reply"));
277 /* Remove the old cache entry */
278 silc_idcache_del_by_context(global ? server->global_list->clients :
279 server->local_list->clients, client);
281 silc_free(client->nickname);
282 silc_free(client->username);
283 silc_free(client->userinfo);
284 silc_free(client->servername);
286 client->nickname = nick;
287 client->username = username;
288 client->userinfo = strdup(realname);
289 client->servername = servername;
291 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
292 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
294 /* Create new cache entry */
295 silc_idcache_add(global ? server->global_list->clients :
296 server->local_list->clients, nick, client->id,
298 silc_free(client_id);
301 /* Save channel list if it was sent to us */
302 if (server->server_type == SILC_SERVER) {
303 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
304 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
306 SilcBufferStruct channels_buf, umodes_buf;
307 silc_buffer_set(&channels_buf, tmp, len);
308 silc_buffer_set(&umodes_buf, umodes, len2);
309 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
312 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
315 /* If client is global and is not on any channel then add that we'll
316 expire the entry after a while. */
318 silc_idlist_find_client_by_id(server->global_list, client->id,
320 if (!silc_hash_table_count(client->channels))
321 cache->expire = time(NULL) + 300;
327 if (fingerprint && flen == sizeof(client->data.fingerprint))
328 memcpy(client->data.fingerprint, fingerprint, flen);
330 /* Take Requested Attributes if set. */
331 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
333 silc_free(client->attrs);
334 client->attrs = silc_memdup(tmp, len);
335 client->attrs_len = len;
337 /* Try to take public key from attributes if present and we don't have
338 the key already. Do this only on normal server. Routers do GETKEY
339 for all clients anyway. */
340 if (server->server_type != SILC_ROUTER && !client->data.public_key) {
341 SilcAttributePayload attr;
342 SilcAttributeObjPk pk;
344 SilcDList attrs = silc_attribute_payload_parse(tmp, len);
346 SILC_LOG_DEBUG(("Take client public key from attributes"));
349 silc_dlist_start(attrs);
350 while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
351 if (silc_attribute_get_attribute(attr) ==
352 SILC_ATTRIBUTE_USER_PUBLIC_KEY) {
354 if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
357 /* Take only SILC public keys */
358 if (strcmp(pk.type, "silc-rsa")) {
364 /* Verify that the server provided fingerprint matches the key */
365 silc_hash_make(server->sha1hash, pk.data, pk.data_len, f);
366 if (memcmp(f, client->data.fingerprint, sizeof(f))) {
372 /* Save the public key. */
373 if (!silc_pkcs_public_key_decode(pk.data, pk.data_len,
374 &client->data.public_key)) {
380 SILC_LOG_DEBUG(("Saved client public key from attributes"));
382 /* Add to public key hash table */
383 if (!silc_hash_table_find_by_context(server->pk_hash,
384 client->data.public_key,
386 silc_hash_table_add(server->pk_hash,
387 client->data.public_key, client);
395 silc_attribute_payload_list_free(attrs);
404 /* Handle requested attributes reply in WHOIS from client */
407 silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd)
411 SilcClientEntry client = cmd->sock->user_data;
413 /* Take Requested Attributes if set. */
414 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
416 silc_free(client->attrs);
417 client->attrs = silc_memdup(tmp, len);
418 client->attrs_len = len;
421 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
426 /* Reiceved reply for WHOIS command. We sent the whois request to our
427 primary router, if we are normal server, and thus has now received reply
428 to the command. We will figure out what client originally sent us the
429 command and will send the reply to it. If we are router we will figure
430 out who server sent us the command and send reply to that one. */
432 SILC_SERVER_CMD_REPLY_FUNC(whois)
434 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
435 SilcStatus status, error;
437 COMMAND_CHECK_STATUS;
439 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) {
440 if (!silc_server_command_reply_whois_save(cmd))
443 if (!silc_server_command_reply_whois_save_client(cmd))
447 /* Pending callbacks are not executed if this was an list entry */
448 if (status != SILC_STATUS_OK &&
449 status != SILC_STATUS_LIST_END) {
450 silc_server_command_reply_free(cmd);
455 silc_server_command_process_error(cmd, error);
456 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
457 silc_server_command_reply_free(cmd);
461 silc_server_command_process_error(cmd, error);
462 silc_server_command_reply_free(cmd);
465 /* Caches the received WHOWAS information for a short period of time. */
468 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
470 SilcServer server = cmd->server;
471 SilcUInt32 len, id_len;
472 unsigned char *id_data;
473 char *nickname, *username, *realname, *servername = NULL;
474 SilcClientID *client_id;
475 SilcClientEntry client;
476 SilcIDCacheEntry cache = NULL;
480 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
481 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
482 username = silc_argument_get_arg_type(cmd->args, 4, &len);
483 if (!id_data || !nickname || !username)
486 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
488 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
492 /* Check for valid username */
493 username = silc_identifier_check(username, strlen(username),
494 SILC_STRING_UTF8, 128, NULL);
496 SILC_LOG_ERROR(("Malformed username received in WHOWAS reply"));
500 /* Check if we have this client cached already. */
502 client = silc_idlist_find_client_by_id(server->local_list, client_id,
505 client = silc_idlist_find_client_by_id(server->global_list,
506 client_id, FALSE, &cache);
511 /* If router did not find such Client ID in its lists then this must
512 be bogus client or some router in the net is buggy. */
513 if (server->server_type != SILC_SERVER) {
518 /* Take hostname out of nick string if it includes it. */
519 silc_parse_userfqdn(nickname, &nick, &servername);
522 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
525 SILC_LOG_ERROR(("Malformed nickname received in WHOWAS reply"));
532 /* We don't have that client anywhere, add it. The client is added
533 to global list since server didn't have it in the lists so it must be
535 client = silc_idlist_add_client(server->global_list, nick, username,
537 silc_id_dup(client_id, SILC_ID_CLIENT),
538 cmd->sock->user_data, NULL,
539 SILC_ID_CACHE_EXPIRE_DEF);
541 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
547 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
548 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
549 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
550 client->servername = servername;
552 /* We have the client already, update the data */
554 /* Take hostname out of nick string if it includes it. */
555 silc_parse_userfqdn(nickname, &nick, &servername);
558 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
561 SILC_LOG_ERROR(("Malformed nickname received in WHOWAS reply"));
568 silc_free(client->nickname);
569 silc_free(client->username);
570 silc_free(client->servername);
572 client->nickname = nick;
573 client->username = username;
574 client->servername = servername;
575 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
576 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
578 /* Remove the old cache entry and create a new one */
579 silc_idcache_del_by_context(global ? server->global_list->clients :
580 server->local_list->clients, client);
581 silc_idcache_add(global ? server->global_list->clients :
582 server->local_list->clients, nick, client->id,
586 /* If client is global and is not on any channel then add that we'll
587 expire the entry after a while. */
589 silc_idlist_find_client_by_id(server->global_list, client->id,
591 if (!silc_hash_table_count(client->channels))
592 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
597 silc_free(client_id);
603 /* Received reply for WHOWAS command. Cache the client information only for
604 a short period of time. */
606 SILC_SERVER_CMD_REPLY_FUNC(whowas)
608 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
609 SilcStatus status, error;
611 COMMAND_CHECK_STATUS;
613 if (!silc_server_command_reply_whowas_save(cmd))
616 /* Pending callbacks are not executed if this was an list entry */
617 if (status != SILC_STATUS_OK &&
618 status != SILC_STATUS_LIST_END) {
619 silc_server_command_reply_free(cmd);
624 silc_server_command_process_error(cmd, error);
625 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
626 silc_server_command_reply_free(cmd);
630 silc_server_command_process_error(cmd, error);
631 silc_server_command_reply_free(cmd);
634 /* Caches the received IDENTIFY information. */
637 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
639 SilcServer server = cmd->server;
640 SilcUInt32 len, id_len;
641 unsigned char *id_data;
643 SilcClientID *client_id = NULL;
644 SilcServerID *server_id = NULL;
645 SilcChannelID *channel_id = NULL;
646 SilcClientEntry client;
647 SilcServerEntry server_entry;
648 SilcChannelEntry channel;
651 SilcIDPayload idp = NULL;
655 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
658 idp = silc_id_payload_parse(id_data, id_len);
662 name = silc_argument_get_arg_type(cmd->args, 3, &len);
663 info = silc_argument_get_arg_type(cmd->args, 4, &len);
665 id_type = silc_id_payload_get_type(idp);
669 client_id = silc_id_payload_get_id(idp);
673 SILC_LOG_DEBUG(("Received client information"));
675 client = silc_idlist_find_client_by_id(server->local_list,
676 client_id, FALSE, NULL);
678 client = silc_idlist_find_client_by_id(server->global_list, client_id,
683 /* If router did not find such Client ID in its lists then this must
684 be bogus client or some router in the net is buggy. */
685 if (server->server_type != SILC_SERVER)
690 silc_parse_userfqdn(name, &nick, NULL);
693 name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
696 SILC_LOG_ERROR(("Malformed nickname received in IDENTIFY reply"));
703 /* We don't have that client anywhere, add it. The client is added
704 to global list since server didn't have it in the lists so it must be
706 client = silc_idlist_add_client(server->global_list, nick,
707 info ? strdup(info) : NULL, NULL,
708 client_id, cmd->sock->user_data,
709 NULL, time(NULL) + 300);
711 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
715 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
716 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
717 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
719 /* We have the client already, update the data */
721 SILC_LOG_DEBUG(("Updating client data"));
725 silc_parse_userfqdn(name, &nick, NULL);
728 name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
731 SILC_LOG_ERROR(("Malformed nickname received in IDENTIFY reply"));
737 /* Remove the old cache entry */
738 silc_idcache_del_by_context(global ? server->global_list->clients :
739 server->local_list->clients, client);
741 silc_free(client->nickname);
742 client->nickname = nick;
746 silc_free(client->username);
747 client->username = strdup(info);
750 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
751 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
754 /* Add new cache entry */
755 silc_idcache_add(global ? server->global_list->clients :
756 server->local_list->clients, nick, client->id,
757 client, expire, NULL);
760 /* If client is global and is not on any channel then add that we'll
761 expire the entry after a while. */
762 if (global && server->server_type == SILC_SERVER) {
763 SilcIDCacheEntry cache = NULL;
764 silc_idlist_find_client_by_id(server->global_list, client->id,
766 if (!silc_hash_table_count(client->channels))
767 cache->expire = time(NULL) + 300;
772 silc_free(client_id);
781 server_id = silc_id_payload_get_id(idp);
785 SILC_LOG_DEBUG(("Received server information"));
787 server_entry = silc_idlist_find_server_by_id(server->local_list,
788 server_id, FALSE, NULL);
790 server_entry = silc_idlist_find_server_by_id(server->global_list,
791 server_id, FALSE, NULL);
793 /* If router did not find such Server ID in its lists then this must
794 be bogus server or some router in the net is buggy. */
795 if (server->server_type != SILC_SERVER)
798 /* We don't have that server anywhere, add it. */
799 server_entry = silc_idlist_add_server(server->global_list,
801 server_id, server->router,
802 SILC_PRIMARY_ROUTE(server));
804 silc_free(server_id);
807 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
808 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
809 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
813 silc_free(server_id);
816 case SILC_ID_CHANNEL:
820 channel_id = silc_id_payload_get_id(idp);
824 SILC_LOG_DEBUG(("Received channel information"));
826 channel = silc_idlist_find_channel_by_name(server->local_list,
829 channel = silc_idlist_find_channel_by_name(server->global_list,
832 /* If router did not find such Channel ID in its lists then this must
833 be bogus channel or some router in the net is buggy. */
834 if (server->server_type != SILC_SERVER)
837 /* We don't have that channel anywhere, add it. */
838 channel = silc_idlist_add_channel(server->global_list, strdup(name),
839 SILC_CHANNEL_MODE_NONE, channel_id,
840 server->router, NULL, NULL, 0);
842 silc_free(channel_id);
848 silc_free(channel_id);
852 silc_id_payload_free(idp);
856 silc_id_payload_free(idp);
860 /* Received reply for forwarded IDENTIFY command. We have received the
861 requested identify information now and we will cache it. After this we
862 will call the pending command so that the requestee gets the information
865 SILC_SERVER_CMD_REPLY_FUNC(identify)
867 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
868 SilcStatus status, error;
870 COMMAND_CHECK_STATUS;
872 if (!silc_server_command_reply_identify_save(cmd))
875 /* Pending callbacks are not executed if this was an list entry */
876 if (status != SILC_STATUS_OK &&
877 status != SILC_STATUS_LIST_END) {
878 silc_server_command_reply_free(cmd);
883 silc_server_command_process_error(cmd, error);
884 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
885 silc_server_command_reply_free(cmd);
889 silc_server_command_process_error(cmd, error);
890 silc_server_command_reply_free(cmd);
893 /* Received reply fro INFO command. Cache the server and its information */
895 SILC_SERVER_CMD_REPLY_FUNC(info)
897 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
898 SilcServer server = cmd->server;
899 SilcStatus status, error;
900 SilcServerEntry entry;
901 SilcServerID *server_id;
903 unsigned char *tmp, *name = NULL;
905 COMMAND_CHECK_STATUS;
908 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
911 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
916 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
920 /* Check server name */
921 name = silc_identifier_check(name, tmp_len, SILC_STRING_UTF8,
926 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
929 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
932 /* Add the server to global list */
933 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
934 entry = silc_idlist_add_server(server->global_list, name, 0,
935 server_id, cmd->sock->user_data,
938 silc_free(server_id);
942 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
946 /* Get the info string */
947 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
951 entry->server_info = tmp ? strdup(tmp) : NULL;
956 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
958 silc_server_command_reply_free(cmd);
961 /* Received reply fro MOTD command. */
963 SILC_SERVER_CMD_REPLY_FUNC(motd)
965 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
966 SilcServer server = cmd->server;
967 SilcStatus status, error;
968 SilcServerEntry entry = NULL;
969 SilcServerID *server_id;
973 COMMAND_CHECK_STATUS;
976 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
979 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
983 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
986 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
991 /* If router did not find such Server ID in its lists then this must
992 be bogus client or some router in the net is buggy. */
993 if (server->server_type != SILC_SERVER)
996 /* entry isn't known so we IDENTIFY it. otherwise the
997 silc_server_command_motd won't know about it and tell
998 the client that there is no such server */
999 buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
1000 ++server->cmd_ident, 5,
1001 1, NULL, 0, 2, NULL, 0,
1002 3, NULL, 0, 4, NULL, 0,
1004 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1005 SILC_PACKET_COMMAND, 0, buffer->data,
1007 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1009 silc_server_command_reply_motd,
1011 silc_buffer_free(buffer);
1017 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1024 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
1026 silc_server_command_reply_free(cmd);
1032 /* Received reply for forwarded JOIN command. Router has created or joined
1033 the client to the channel. We save some channel information locally
1036 SILC_SERVER_CMD_REPLY_FUNC(join)
1038 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1039 SilcServer server = cmd->server;
1040 SilcIDCacheEntry cache = NULL;
1041 SilcStatus status, error;
1043 SilcClientID *client_id = NULL;
1044 SilcChannelEntry entry;
1045 SilcHmac hmac = NULL;
1046 SilcUInt32 id_len, len, list_count;
1047 unsigned char *id_string;
1048 char *channel_name, *tmp;
1049 SilcUInt32 mode, created;
1050 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
1051 SilcPublicKey founder_key = NULL;
1053 COMMAND_CHECK_STATUS;
1055 /* Get channel name */
1056 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
1060 /* Get channel ID */
1061 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
1066 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
1069 client_id = silc_id_payload_parse_id(tmp, len, NULL);
1074 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1077 SILC_GET32_MSB(mode, tmp);
1079 /* Get created boolean value */
1080 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1083 SILC_GET32_MSB(created, tmp);
1084 if (created != 0 && created != 1)
1087 /* Get channel key */
1088 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
1090 keyp = silc_buffer_alloc(len);
1091 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
1092 silc_buffer_put(keyp, tmp, len);
1095 /* Parse the Channel ID */
1096 id = silc_id_payload_parse_id(id_string, id_len, NULL);
1101 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1103 if (!silc_hmac_alloc(tmp, NULL, &hmac))
1107 /* Get the list count */
1108 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1111 SILC_GET32_MSB(list_count, tmp);
1113 /* Get Client ID list */
1114 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1118 client_id_list = silc_buffer_alloc(len);
1119 silc_buffer_pull_tail(client_id_list, len);
1120 silc_buffer_put(client_id_list, tmp, len);
1122 /* Get client mode list */
1123 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1127 client_mode_list = silc_buffer_alloc(len);
1128 silc_buffer_pull_tail(client_mode_list, len);
1129 silc_buffer_put(client_mode_list, tmp, len);
1131 /* Get founder key */
1132 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1134 silc_pkcs_public_key_payload_decode(tmp, len, &founder_key);
1136 /* See whether we already have the channel. */
1137 entry = silc_idlist_find_channel_by_name(server->local_list,
1138 channel_name, &cache);
1140 /* Add new channel */
1142 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1143 (created == 0 ? "existing" : "created"), channel_name,
1144 silc_id_render(id, SILC_ID_CHANNEL)));
1146 /* If the channel is found from global list we must move it to the
1148 entry = silc_idlist_find_channel_by_name(server->global_list,
1149 channel_name, &cache);
1151 silc_idlist_del_channel(server->global_list, entry);
1153 /* Add the channel to our local list. */
1154 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1155 SILC_CHANNEL_MODE_NONE, id,
1156 server->router, NULL, hmac, 0);
1162 server->stat.my_channels++;
1163 server->stat.channels++;
1165 /* The entry exists. */
1167 /* If ID has changed, then update it to the cache too. */
1168 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
1169 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
1171 entry->disabled = FALSE;
1173 /* Remove the founder auth data if the mode is not set but we have
1174 them in the entry */
1175 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1176 silc_pkcs_public_key_free(entry->founder_key);
1177 entry->founder_key = NULL;
1182 if (entry->founder_key)
1183 silc_pkcs_public_key_free(entry->founder_key);
1184 entry->founder_key = founder_key;
1188 if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1189 silc_free(entry->hmac_name);
1190 entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1193 /* Get the ban list */
1194 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1195 if (tmp && len > 2) {
1196 SilcArgumentPayload iargs;
1198 SILC_GET16_MSB(iargc, tmp);
1199 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1201 /* Delete old ban list */
1202 if (entry->ban_list)
1203 silc_hash_table_free(entry->ban_list);
1205 silc_hash_table_alloc(0, silc_hash_ptr,
1207 silc_server_inviteban_destruct, entry, TRUE);
1209 /* Add new ban list */
1210 silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1211 silc_argument_payload_free(iargs);
1215 /* Get the invite list */
1216 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1217 if (tmp && len > 2) {
1218 SilcArgumentPayload iargs;
1220 SILC_GET16_MSB(iargc, tmp);
1221 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1223 /* Delete old invite list */
1224 if (entry->invite_list)
1225 silc_hash_table_free(entry->invite_list);
1226 entry->invite_list =
1227 silc_hash_table_alloc(0, silc_hash_ptr,
1229 silc_server_inviteban_destruct, entry, TRUE);
1231 /* Add new invite list */
1232 silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1233 silc_argument_payload_free(iargs);
1238 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1240 silc_free(entry->topic);
1241 entry->topic = strdup(tmp);
1244 /* Get channel public key list */
1245 tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1246 if (tmp && server->server_type == SILC_SERVER)
1247 silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1249 /* The the user limit */
1250 tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1251 if (tmp && len == 4)
1252 SILC_GET32_MSB(entry->user_limit, tmp);
1254 /* If channel was not created we know there is global users on the
1256 entry->global_users = (created == 0 ? TRUE : FALSE);
1258 /* If channel was just created the mask must be zero */
1259 if (!entry->global_users && mode) {
1260 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
1261 "new channel, forcing it to zero", cmd->sock->hostname));
1265 /* Save channel mode */
1268 /* Save channel key */
1270 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1271 silc_server_save_channel_key(server, keyp, entry);
1272 silc_buffer_free(keyp);
1275 /* Save the users to the channel */
1276 silc_server_save_users_on_channel(server, cmd->sock, entry,
1277 client_id, client_id_list,
1278 client_mode_list, list_count);
1279 entry->users_resolved = TRUE;
1282 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1285 silc_hmac_free(hmac);
1286 silc_free(client_id);
1287 silc_server_command_reply_free(cmd);
1289 silc_pkcs_public_key_free(founder_key);
1291 silc_buffer_free(client_id_list);
1292 if (client_mode_list)
1293 silc_buffer_free(client_mode_list);
1296 /* Received reply to STATS command. */
1298 SILC_SERVER_CMD_REPLY_FUNC(stats)
1300 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1301 SilcServer server = cmd->server;
1302 SilcStatus status, error;
1305 SilcBufferStruct buf;
1307 COMMAND_CHECK_STATUS;
1309 /* Get statistics structure */
1310 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1311 if (server->server_type != SILC_ROUTER && tmp) {
1312 silc_buffer_set(&buf, tmp, tmp_len);
1313 silc_buffer_unformat(&buf,
1314 SILC_STR_UI_INT(NULL),
1315 SILC_STR_UI_INT(NULL),
1316 SILC_STR_UI_INT(NULL),
1317 SILC_STR_UI_INT(NULL),
1318 SILC_STR_UI_INT(NULL),
1319 SILC_STR_UI_INT(NULL),
1320 SILC_STR_UI_INT(&server->stat.cell_clients),
1321 SILC_STR_UI_INT(&server->stat.cell_channels),
1322 SILC_STR_UI_INT(&server->stat.cell_servers),
1323 SILC_STR_UI_INT(&server->stat.clients),
1324 SILC_STR_UI_INT(&server->stat.channels),
1325 SILC_STR_UI_INT(&server->stat.servers),
1326 SILC_STR_UI_INT(&server->stat.routers),
1327 SILC_STR_UI_INT(&server->stat.server_ops),
1328 SILC_STR_UI_INT(&server->stat.router_ops),
1333 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1335 silc_server_command_reply_free(cmd);
1338 SILC_SERVER_CMD_REPLY_FUNC(users)
1340 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1341 SilcServer server = cmd->server;
1342 SilcStatus status, error;
1343 SilcChannelEntry channel;
1344 SilcChannelID *channel_id = NULL;
1345 SilcBuffer client_id_list;
1346 SilcBuffer client_mode_list;
1349 SilcUInt32 list_count;
1351 COMMAND_CHECK_STATUS;
1353 /* Get channel ID */
1354 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1357 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1361 /* Get channel entry */
1362 channel = silc_idlist_find_channel_by_id(server->local_list,
1365 channel = silc_idlist_find_channel_by_id(server->global_list,
1370 if (server->server_type != SILC_SERVER)
1373 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1374 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1375 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1376 1, 5, idp->data, idp->len);
1377 silc_buffer_free(idp);
1379 /* Register pending command callback. After we've received the channel
1380 information we will reprocess this command reply by re-calling this
1381 USERS command reply callback. */
1382 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1384 silc_server_command_reply_users, cmd);
1389 /* Get the list count */
1390 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1393 SILC_GET32_MSB(list_count, tmp);
1395 /* Get Client ID list */
1396 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1400 client_id_list = silc_buffer_alloc(tmp_len);
1401 silc_buffer_pull_tail(client_id_list, tmp_len);
1402 silc_buffer_put(client_id_list, tmp, tmp_len);
1404 /* Get client mode list */
1405 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1409 client_mode_list = silc_buffer_alloc(tmp_len);
1410 silc_buffer_pull_tail(client_mode_list, tmp_len);
1411 silc_buffer_put(client_mode_list, tmp, tmp_len);
1413 /* Save the users to the channel */
1414 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1415 client_id_list, client_mode_list,
1418 channel->global_users = silc_server_channel_has_global(channel);
1419 channel->users_resolved = TRUE;
1421 silc_buffer_free(client_id_list);
1422 silc_buffer_free(client_mode_list);
1425 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1426 silc_free(channel_id);
1428 silc_server_command_reply_free(cmd);
1431 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1433 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1434 SilcServer server = cmd->server;
1435 SilcStatus status, error;
1436 SilcClientEntry client = NULL;
1437 SilcServerEntry server_entry = NULL;
1438 SilcClientID *client_id = NULL;
1439 SilcServerID *server_id = NULL;
1442 SilcIDPayload idp = NULL;
1444 SilcPublicKey public_key = NULL;
1446 COMMAND_CHECK_STATUS;
1448 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1451 idp = silc_id_payload_parse(tmp, len);
1455 /* Get the public key payload */
1456 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1460 /* Decode the public key payload */
1461 if (!silc_pkcs_public_key_payload_decode(tmp, len, &public_key))
1464 id_type = silc_id_payload_get_type(idp);
1465 if (id_type == SILC_ID_CLIENT) {
1466 client_id = silc_id_payload_get_id(idp);
1468 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1471 client = silc_idlist_find_client_by_id(server->global_list,
1472 client_id, TRUE, NULL);
1477 if (!client->data.public_key) {
1478 if (!silc_hash_table_find_by_context(server->pk_hash, public_key,
1480 silc_hash_table_add(server->pk_hash, public_key, client);
1482 client->data.public_key = public_key;
1485 } else if (id_type == SILC_ID_SERVER) {
1486 server_id = silc_id_payload_get_id(idp);
1488 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1490 if (!server_entry) {
1491 server_entry = silc_idlist_find_server_by_id(server->global_list,
1492 server_id, TRUE, NULL);
1497 server_entry->data.public_key = public_key;
1504 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1506 silc_id_payload_free(idp);
1507 silc_free(client_id);
1508 silc_free(server_id);
1510 silc_pkcs_public_key_free(public_key);
1512 silc_server_command_reply_free(cmd);
1515 SILC_SERVER_CMD_REPLY_FUNC(list)
1517 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1518 SilcServer server = cmd->server;
1519 SilcStatus status, error;
1520 SilcChannelID *channel_id = NULL;
1521 SilcChannelEntry channel;
1522 SilcIDCacheEntry cache;
1524 unsigned char *tmp, *name, *topic;
1525 SilcUInt32 usercount = 0;
1526 bool global_list = FALSE;
1528 COMMAND_CHECK_STATUS;
1530 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1531 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1535 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1536 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1537 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1539 SILC_GET32_MSB(usercount, tmp);
1541 /* Add the channel entry if we do not have it already */
1542 channel = silc_idlist_find_channel_by_name(server->local_list,
1545 channel = silc_idlist_find_channel_by_name(server->global_list,
1550 /* If router did not find such channel in its lists then this must
1551 be bogus channel or some router in the net is buggy. */
1552 if (server->server_type != SILC_SERVER)
1555 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1556 SILC_CHANNEL_MODE_NONE, channel_id,
1557 server->router, NULL, NULL,
1563 /* Found, update expiry */
1564 if (global_list && server->server_type == SILC_SERVER)
1565 cache->expire = time(NULL) + 60;
1568 channel->user_count = usercount;
1571 silc_free(channel->topic);
1572 channel->topic = strdup(topic);
1575 /* Pending callbacks are not executed if this was an list entry */
1576 if (status != SILC_STATUS_OK &&
1577 status != SILC_STATUS_LIST_END) {
1578 silc_server_command_reply_free(cmd);
1582 /* Now purge all old entries from the global list, otherwise we'll might
1583 have non-existent entries for long periods of time in the cache. */
1584 silc_idcache_purge(server->global_list->channels);
1587 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1588 silc_free(channel_id);
1590 silc_server_command_reply_free(cmd);
1593 SILC_SERVER_CMD_REPLY_FUNC(watch)
1595 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1596 SilcStatus status, error;
1598 COMMAND_CHECK_STATUS;
1601 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1603 silc_server_command_reply_free(cmd);
1606 SILC_SERVER_CMD_REPLY_FUNC(ping)
1608 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1609 SilcStatus status, error;
1611 COMMAND_CHECK_STATUS;
1614 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1616 silc_server_command_reply_free(cmd);