5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005, 2007 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 /* We have the client already, update the data */
242 SILC_LOG_DEBUG(("Updating client data"));
245 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
247 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
250 SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOIS reply "
252 hostname ? hostname : "", nick));
257 silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
258 if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128)) {
259 SILC_LOG_ERROR(("Malformed username '%s' received in WHOIS reply "
261 hostname ? hostname : "", tmp));
266 silc_idcache_update_by_context(global ? server->global_list->clients :
267 server->local_list->clients, client, NULL,
270 silc_free(client->nickname);
271 silc_free(client->username);
272 silc_free(client->userinfo);
273 silc_free(client->servername);
275 client->nickname = strdup(nick);
276 client->username = strdup(username);
277 client->userinfo = strdup(realname);
278 client->servername = servername[0] ? strdup(servername) : NULL;
280 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
281 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
284 /* Save channel list if it was sent to us */
285 if (server->server_type == SILC_SERVER) {
286 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
287 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
289 SilcBufferStruct channels_buf, umodes_buf;
290 silc_buffer_set(&channels_buf, tmp, len);
291 silc_buffer_set(&umodes_buf, umodes, len2);
292 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
295 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
299 if (fingerprint && flen == sizeof(client->data.fingerprint))
300 memcpy(client->data.fingerprint, fingerprint, flen);
302 /* Take Requested Attributes if set. */
303 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
305 silc_free(client->attrs);
306 client->attrs = silc_memdup(tmp, len);
307 client->attrs_len = len;
309 /* Try to take public key from attributes if present and we don't have
310 the key already. Do this only on normal server. Routers do GETKEY
311 for all clients anyway. */
312 if (server->server_type != SILC_ROUTER && !client->data.public_key) {
313 SilcAttributePayload attr;
314 SilcAttributeObjPk pk;
315 unsigned char f[SILC_HASH_MAXLEN];
316 SilcDList attrs = silc_attribute_payload_parse(tmp, len);
318 SILC_LOG_DEBUG(("Take client public key from attributes"));
321 silc_dlist_start(attrs);
322 while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
323 if (silc_attribute_get_attribute(attr) ==
324 SILC_ATTRIBUTE_USER_PUBLIC_KEY) {
326 if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
329 /* Take only SILC public keys */
330 if (strcmp(pk.type, "silc-rsa")) {
336 /* Verify that the server provided fingerprint matches the key */
337 silc_hash_make(server->sha1hash, pk.data, pk.data_len, f);
338 if (memcmp(f, client->data.fingerprint, sizeof(f))) {
344 /* Save the public key. */
345 if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC,
346 pk.data, pk.data_len,
347 &client->data.public_key)) {
353 SILC_LOG_DEBUG(("Saved client public key from attributes"));
355 /* Add client's public key to repository */
356 if (!silc_server_get_public_key_by_client(server, client, NULL))
357 silc_skr_add_public_key_simple(server->repository,
358 client->data.public_key,
359 SILC_SKR_USAGE_IDENTIFICATION,
368 silc_attribute_payload_list_free(attrs);
376 /* Handle requested attributes reply in WHOIS from client */
379 silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd)
383 SilcClientEntry client = silc_packet_get_context(cmd->sock);
385 /* Take Requested Attributes if set. */
386 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
388 silc_free(client->attrs);
389 client->attrs = silc_memdup(tmp, len);
390 client->attrs_len = len;
393 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
398 /* Reiceved reply for WHOIS command. We sent the whois request to our
399 primary router, if we are normal server, and thus has now received reply
400 to the command. We will figure out what client originally sent us the
401 command and will send the reply to it. If we are router we will figure
402 out who server sent us the command and send reply to that one. */
404 SILC_SERVER_CMD_REPLY_FUNC(whois)
406 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
407 SilcIDListData idata = silc_packet_get_context(cmd->sock);
408 SilcStatus status, error;
410 COMMAND_CHECK_STATUS;
412 if (idata->conn_type != SILC_CONN_CLIENT) {
413 if (!silc_server_command_reply_whois_save(cmd))
416 if (!silc_server_command_reply_whois_save_client(cmd))
420 /* Pending callbacks are not executed if this was an list entry */
421 if (status != SILC_STATUS_OK &&
422 status != SILC_STATUS_LIST_END) {
423 silc_server_command_reply_free(cmd);
428 silc_server_command_process_error(cmd, error);
429 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
430 silc_server_command_reply_free(cmd);
434 silc_server_command_process_error(cmd, error);
435 silc_server_command_reply_free(cmd);
438 /* Caches the received WHOWAS information for a short period of time. */
441 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
443 SilcServer server = cmd->server;
444 SilcUInt32 len, id_len;
445 unsigned char *id_data;
446 char *nickname, *username, *realname;
448 SilcClientEntry client;
449 SilcIDCacheEntry cache = NULL;
450 char nick[128 + 1], servername[256 + 1], uname[128 + 1];
452 const char *hostname, *ip;
454 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
455 NULL, &hostname, &ip, NULL);
457 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
458 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
459 username = silc_argument_get_arg_type(cmd->args, 4, &len);
460 if (!id_data || !nickname || !username)
463 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
465 if (!silc_id_payload_parse_id(id_data, id_len, &id))
468 /* Check if we have this client cached already. */
470 client = silc_idlist_find_client_by_id(server->local_list,
474 client = silc_idlist_find_client_by_id(server->global_list,
481 /* If router did not find such Client ID in its lists then this must
482 be bogus client or some router in the net is buggy. */
483 if (server->server_type != SILC_SERVER)
486 /* Take hostname out of nick string if it includes it. */
487 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
490 /* We don't have that client anywhere, add it. The client is added
491 to global list since server didn't have it in the lists so it must be
493 client = silc_idlist_add_client(server->global_list,
494 strdup(nick), username,
496 silc_id_dup(SILC_ID_GET_ID(id),
498 silc_packet_get_context(cmd->sock), NULL);
500 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
504 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
505 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
506 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
507 client->servername = servername[0] ? strdup(servername) : NULL;
509 /* We have the client already, update the data */
512 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
514 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
517 SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOWAS reply "
519 nick, hostname ? hostname : ""));
524 silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
525 if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128))
528 silc_free(client->nickname);
529 silc_free(client->username);
530 silc_free(client->servername);
532 client->nickname = strdup(nick);
533 client->username = strdup(username);
534 client->servername = servername[0] ? strdup(servername) : NULL;
535 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
536 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
537 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
539 /* Update cache entry */
540 silc_idcache_update_by_context(global ? server->global_list->clients :
541 server->local_list->clients, client, NULL,
545 /* If client is global and is not on any channel then add that we'll
546 expire the entry after a while. */
548 client = silc_idlist_find_client_by_id(server->global_list, client->id,
550 if (client && !silc_hash_table_count(client->channels)) {
551 client->data.created = silc_time();
552 silc_dlist_del(server->expired_clients, client);
553 silc_dlist_add(server->expired_clients, client);
560 /* Received reply for WHOWAS command. Cache the client information only for
561 a short period of time. */
563 SILC_SERVER_CMD_REPLY_FUNC(whowas)
565 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
566 SilcStatus status, error;
568 COMMAND_CHECK_STATUS;
570 if (!silc_server_command_reply_whowas_save(cmd))
573 /* Pending callbacks are not executed if this was an list entry */
574 if (status != SILC_STATUS_OK &&
575 status != SILC_STATUS_LIST_END) {
576 silc_server_command_reply_free(cmd);
581 silc_server_command_process_error(cmd, error);
582 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
583 silc_server_command_reply_free(cmd);
587 silc_server_command_process_error(cmd, error);
588 silc_server_command_reply_free(cmd);
591 /* Caches the received IDENTIFY information. */
594 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
596 SilcServer server = cmd->server;
597 SilcUInt32 len, id_len;
598 unsigned char *id_data;
600 SilcClientID client_id;
601 SilcServerID server_id;
602 SilcChannelID*channel_id;
603 SilcClientEntry client;
604 SilcServerEntry server_entry;
605 SilcChannelEntry channel;
608 SilcIDPayload idp = NULL;
611 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
614 idp = silc_id_payload_parse(id_data, id_len);
618 name = silc_argument_get_arg_type(cmd->args, 3, &len);
619 info = silc_argument_get_arg_type(cmd->args, 4, &len);
621 id_type = silc_id_payload_get_type(idp);
625 if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
628 SILC_LOG_DEBUG(("Received client information"));
630 client = silc_idlist_find_client_by_id(server->local_list,
631 &client_id, FALSE, NULL);
633 client = silc_idlist_find_client_by_id(server->global_list, &client_id,
638 /* If router did not find such Client ID in its lists then this must
639 be bogus client or some router in the net is buggy. */
640 if (server->server_type != SILC_SERVER)
645 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
647 /* We don't have that client anywhere, add it. The client is added
648 to global list since server didn't have it in the lists so it must be
650 client = silc_idlist_add_client(server->global_list,
651 nick[0] ? nick : NULL, info, NULL,
652 silc_id_dup(&client_id, SILC_ID_CLIENT),
653 silc_packet_get_context(cmd->sock),
656 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
660 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
661 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
662 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
664 /* We have the client already, update the data */
666 SILC_LOG_DEBUG(("Updating client data"));
670 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
673 name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
676 SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY "
681 silc_free(client->nickname);
682 client->nickname = strdup(nick);
684 /* Update the context */
685 silc_idcache_update_by_context(global ? server->global_list->clients :
686 server->local_list->clients, client,
691 silc_free(client->username);
692 client->username = strdup(info);
695 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
696 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
705 if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
708 SILC_LOG_DEBUG(("Received server information"));
710 server_entry = silc_idlist_find_server_by_id(server->local_list,
711 &server_id, FALSE, NULL);
713 server_entry = silc_idlist_find_server_by_id(server->global_list,
714 &server_id, FALSE, NULL);
716 /* If router did not find such Server ID in its lists then this must
717 be bogus server or some router in the net is buggy. */
718 if (server->server_type != SILC_SERVER)
721 /* We don't have that server anywhere, add it. */
722 server_entry = silc_idlist_add_server(server->global_list,
724 silc_id_dup(&server_id,
727 SILC_PRIMARY_ROUTE(server));
731 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
732 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
733 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
738 case SILC_ID_CHANNEL:
742 if (!silc_id_payload_get_id(idp, &channel_id, sizeof(channel_id)))
745 SILC_LOG_DEBUG(("Received channel information"));
747 /* Check channel name */
748 info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
753 channel = silc_idlist_find_channel_by_name(server->local_list,
756 channel = silc_idlist_find_channel_by_name(server->global_list,
759 /* If router did not find such Channel ID in its lists then this must
760 be bogus channel or some router in the net is buggy. */
761 if (server->server_type != SILC_SERVER) {
766 /* We don't have that channel anywhere, add it. */
767 channel = silc_idlist_add_channel(server->global_list, strdup(name),
768 SILC_CHANNEL_MODE_NONE,
769 silc_id_dup(&channel_id,
771 server->router, NULL, NULL, 0);
782 silc_id_payload_free(idp);
786 silc_id_payload_free(idp);
790 /* Received reply for forwarded IDENTIFY command. We have received the
791 requested identify information now and we will cache it. After this we
792 will call the pending command so that the requestee gets the information
795 SILC_SERVER_CMD_REPLY_FUNC(identify)
797 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
798 SilcStatus status, error;
800 COMMAND_CHECK_STATUS;
802 if (!silc_server_command_reply_identify_save(cmd))
805 /* Pending callbacks are not executed if this was an list entry */
806 if (status != SILC_STATUS_OK &&
807 status != SILC_STATUS_LIST_END) {
808 silc_server_command_reply_free(cmd);
813 silc_server_command_process_error(cmd, error);
814 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
815 silc_server_command_reply_free(cmd);
819 silc_server_command_process_error(cmd, error);
820 silc_server_command_reply_free(cmd);
823 /* Received reply fro INFO command. Cache the server and its information */
825 SILC_SERVER_CMD_REPLY_FUNC(info)
827 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
828 SilcServer server = cmd->server;
829 SilcStatus status, error;
830 SilcServerEntry entry;
833 unsigned char *tmp, *name;
835 COMMAND_CHECK_STATUS;
838 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
842 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
846 entry = silc_idlist_find_server_by_id(server->local_list,
850 entry = silc_idlist_find_server_by_id(server->global_list,
854 /* Add the server to global list */
855 entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
856 silc_id_dup(SILC_ID_GET_ID(id),
858 silc_packet_get_context(cmd->sock),
863 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
867 /* Get the info string */
868 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
872 entry->server_info = tmp ? strdup(tmp) : NULL;
875 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
877 silc_server_command_reply_free(cmd);
880 /* Received reply fro MOTD command. */
882 SILC_SERVER_CMD_REPLY_FUNC(motd)
884 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
885 SilcServer server = cmd->server;
886 SilcStatus status, error;
887 SilcServerEntry entry = NULL;
892 COMMAND_CHECK_STATUS;
895 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
898 entry = silc_idlist_find_server_by_id(server->local_list,
902 entry = silc_idlist_find_server_by_id(server->global_list,
908 /* If router did not find such Server ID in its lists then this must
909 be bogus client or some router in the net is buggy. */
910 if (server->server_type != SILC_SERVER)
914 cmd->server->stat.commands_sent++;
916 /* entry isn't known so we IDENTIFY it. otherwise the
917 silc_server_command_motd won't know about it and tell
918 the client that there is no such server */
919 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
920 buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
921 ++server->cmd_ident, 5,
922 1, NULL, 0, 2, NULL, 0,
923 3, NULL, 0, 4, NULL, 0,
925 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
926 SILC_PACKET_COMMAND, 0, buffer->data,
927 silc_buffer_len(buffer));
928 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
930 silc_server_command_reply_motd,
932 silc_buffer_free(buffer);
938 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
945 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
947 silc_server_command_reply_free(cmd);
953 /* Received reply for forwarded JOIN command. Router has created or joined
954 the client to the channel. We save some channel information locally
957 SILC_SERVER_CMD_REPLY_FUNC(join)
959 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
960 SilcServer server = cmd->server;
961 SilcIDCacheEntry cache = NULL;
962 SilcStatus status, error;
964 SilcChannelEntry entry;
965 SilcHmac hmac = NULL;
966 SilcUInt32 len, list_count;
967 char *channel_name, *channel_namec = NULL, *tmp;
968 SilcUInt32 mode, created;
969 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
970 SilcPublicKey founder_key = NULL;
972 COMMAND_CHECK_STATUS;
974 /* Get channel name */
975 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
980 if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id, NULL))
984 if (!silc_argument_get_decoded(cmd->args, 4, SILC_ARGUMENT_ID, &id2, NULL))
988 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
991 SILC_GET32_MSB(mode, tmp);
993 /* Get created boolean value */
994 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
997 SILC_GET32_MSB(created, tmp);
998 if (created != 0 && created != 1)
1001 /* Get channel key */
1002 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
1004 keyp = silc_buffer_alloc(len);
1005 silc_buffer_pull_tail(keyp, silc_buffer_truelen(keyp));
1006 silc_buffer_put(keyp, tmp, len);
1010 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1012 if (!silc_hmac_alloc(tmp, NULL, &hmac))
1016 /* Get the list count */
1017 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1020 SILC_GET32_MSB(list_count, tmp);
1022 /* Get Client ID list */
1023 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1027 client_id_list = silc_buffer_alloc(len);
1028 silc_buffer_pull_tail(client_id_list, len);
1029 silc_buffer_put(client_id_list, tmp, len);
1031 /* Get client mode list */
1032 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1036 client_mode_list = silc_buffer_alloc(len);
1037 silc_buffer_pull_tail(client_mode_list, len);
1038 silc_buffer_put(client_mode_list, tmp, len);
1040 /* Get founder key */
1041 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1043 silc_public_key_payload_decode(tmp, len, &founder_key);
1045 /* See whether we already have the channel. */
1046 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
1047 SILC_STRING_UTF8, 256, NULL);
1050 entry = silc_idlist_find_channel_by_name(server->local_list,
1051 channel_namec, &cache);
1053 /* Add new channel */
1055 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1056 (created == 0 ? "existing" : "created"), channel_name,
1057 silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL)));
1059 /* If the channel is found from global list we must move it to the
1061 entry = silc_idlist_find_channel_by_name(server->global_list,
1062 channel_namec, &cache);
1064 silc_idlist_del_channel(server->global_list, entry);
1066 /* Add the channel to our local list. */
1067 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1068 SILC_CHANNEL_MODE_NONE,
1069 silc_id_dup(SILC_ID_GET_ID(id),
1071 server->router, NULL, NULL, hmac);
1076 server->stat.my_channels++;
1077 server->stat.channels++;
1079 /* The entry exists. */
1081 /* If ID has changed, then update it to the cache too. */
1082 if (!SILC_ID_CHANNEL_COMPARE(entry->id, SILC_ID_GET_ID(id)))
1083 silc_idlist_replace_channel_id(server->local_list, entry->id,
1084 SILC_ID_GET_ID(id));
1086 entry->disabled = FALSE;
1088 /* Remove the founder auth data if the mode is not set but we have
1089 them in the entry */
1090 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1091 silc_pkcs_public_key_free(entry->founder_key);
1092 entry->founder_key = NULL;
1097 if (entry->founder_key)
1098 silc_pkcs_public_key_free(entry->founder_key);
1099 entry->founder_key = founder_key;
1103 if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1104 silc_free(entry->hmac_name);
1105 entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1108 /* Get the ban list */
1109 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1110 if (tmp && len > 2) {
1111 SilcArgumentPayload iargs;
1113 SILC_GET16_MSB(iargc, tmp);
1114 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1116 /* Delete old ban list */
1117 if (entry->ban_list)
1118 silc_hash_table_free(entry->ban_list);
1120 silc_hash_table_alloc(0, silc_hash_ptr,
1122 silc_server_inviteban_destruct, entry, TRUE);
1124 /* Add new ban list */
1125 silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1126 silc_argument_payload_free(iargs);
1130 /* Get the invite list */
1131 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1132 if (tmp && len > 2) {
1133 SilcArgumentPayload iargs;
1135 SILC_GET16_MSB(iargc, tmp);
1136 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1138 /* Delete old invite list */
1139 if (entry->invite_list)
1140 silc_hash_table_free(entry->invite_list);
1141 entry->invite_list =
1142 silc_hash_table_alloc(0, silc_hash_ptr,
1144 silc_server_inviteban_destruct, entry, TRUE);
1146 /* Add new invite list */
1147 silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1148 silc_argument_payload_free(iargs);
1153 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1155 silc_free(entry->topic);
1156 entry->topic = strdup(tmp);
1159 /* Get channel public key list */
1160 tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1161 if (tmp && server->server_type != SILC_ROUTER)
1162 silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1164 /* The the user limit */
1165 tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1166 if (tmp && len == 4)
1167 SILC_GET32_MSB(entry->user_limit, tmp);
1169 /* If channel was not created we know there is global users on the
1171 entry->global_users = (created == 0 ? TRUE : FALSE);
1173 /* If channel was just created the mask must be zero */
1174 if (!entry->global_users && mode)
1177 /* Save channel mode */
1180 /* Save channel key */
1182 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1183 silc_server_save_channel_key(server, keyp, entry);
1184 silc_buffer_free(keyp);
1187 /* Save the users to the channel */
1188 silc_server_save_users_on_channel(server, cmd->sock, entry,
1189 SILC_ID_GET_ID(id2), client_id_list,
1190 client_mode_list, list_count);
1191 entry->users_resolved = TRUE;
1194 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1196 silc_free(channel_namec);
1198 silc_hmac_free(hmac);
1199 silc_server_command_reply_free(cmd);
1202 silc_pkcs_public_key_free(founder_key);
1204 silc_buffer_free(client_id_list);
1205 if (client_mode_list)
1206 silc_buffer_free(client_mode_list);
1209 /* Received reply to STATS command. */
1211 SILC_SERVER_CMD_REPLY_FUNC(stats)
1213 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1214 SilcServer server = cmd->server;
1215 SilcStatus status, error;
1218 SilcBufferStruct buf;
1220 COMMAND_CHECK_STATUS;
1222 /* Get statistics structure */
1223 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1224 if (server->server_type != SILC_ROUTER && tmp) {
1225 silc_buffer_set(&buf, tmp, tmp_len);
1226 silc_buffer_unformat(&buf,
1227 SILC_STR_UI_INT(NULL),
1228 SILC_STR_UI_INT(NULL),
1229 SILC_STR_UI_INT(NULL),
1230 SILC_STR_UI_INT(NULL),
1231 SILC_STR_UI_INT(NULL),
1232 SILC_STR_UI_INT(NULL),
1233 SILC_STR_UI_INT(&server->stat.cell_clients),
1234 SILC_STR_UI_INT(&server->stat.cell_channels),
1235 SILC_STR_UI_INT(&server->stat.cell_servers),
1236 SILC_STR_UI_INT(&server->stat.clients),
1237 SILC_STR_UI_INT(&server->stat.channels),
1238 SILC_STR_UI_INT(&server->stat.servers),
1239 SILC_STR_UI_INT(&server->stat.routers),
1240 SILC_STR_UI_INT(&server->stat.server_ops),
1241 SILC_STR_UI_INT(&server->stat.router_ops),
1246 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1248 silc_server_command_reply_free(cmd);
1251 SILC_SERVER_CMD_REPLY_FUNC(users)
1253 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1254 SilcServer server = cmd->server;
1255 SilcStatus status, error;
1256 SilcChannelEntry channel;
1258 SilcBuffer client_id_list;
1259 SilcBuffer client_mode_list;
1262 SilcUInt32 list_count;
1264 COMMAND_CHECK_STATUS;
1266 /* Get channel ID */
1267 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1270 /* Get channel entry */
1271 channel = silc_idlist_find_channel_by_id(server->local_list,
1272 SILC_ID_GET_ID(id), NULL);
1274 channel = silc_idlist_find_channel_by_id(server->global_list,
1275 SILC_ID_GET_ID(id), NULL);
1279 if (server->server_type != SILC_SERVER)
1282 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1283 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1284 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1285 1, 5, idp->data, silc_buffer_len(idp));
1286 silc_buffer_free(idp);
1288 /* Register pending command callback. After we've received the channel
1289 information we will reprocess this command reply by re-calling this
1290 USERS command reply callback. */
1291 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1293 silc_server_command_reply_users, cmd);
1298 /* Get the list count */
1299 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1302 SILC_GET32_MSB(list_count, tmp);
1304 /* Get Client ID list */
1305 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1309 client_id_list = silc_buffer_alloc(tmp_len);
1310 silc_buffer_pull_tail(client_id_list, tmp_len);
1311 silc_buffer_put(client_id_list, tmp, tmp_len);
1313 /* Get client mode list */
1314 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1318 client_mode_list = silc_buffer_alloc(tmp_len);
1319 silc_buffer_pull_tail(client_mode_list, tmp_len);
1320 silc_buffer_put(client_mode_list, tmp, tmp_len);
1322 /* Save the users to the channel */
1323 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1324 client_id_list, client_mode_list,
1327 channel->global_users = silc_server_channel_has_global(channel);
1328 channel->users_resolved = TRUE;
1330 silc_buffer_free(client_id_list);
1331 silc_buffer_free(client_mode_list);
1334 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1336 silc_server_command_reply_free(cmd);
1339 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1341 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1342 SilcServer server = cmd->server;
1343 SilcStatus status, error;
1344 SilcClientEntry client = NULL;
1345 SilcServerEntry server_entry = NULL;
1346 SilcClientID client_id;
1347 SilcServerID server_id;
1350 SilcIDPayload idp = NULL;
1352 SilcPublicKey public_key = NULL;
1354 COMMAND_CHECK_STATUS;
1356 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1359 idp = silc_id_payload_parse(tmp, len);
1363 /* Get the public key payload */
1364 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1368 /* Decode the public key payload */
1369 if (!silc_public_key_payload_decode(tmp, len, &public_key))
1372 id_type = silc_id_payload_get_type(idp);
1373 if (id_type == SILC_ID_CLIENT) {
1374 silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
1376 client = silc_idlist_find_client_by_id(server->local_list, &client_id,
1379 client = silc_idlist_find_client_by_id(server->global_list,
1380 &client_id, TRUE, NULL);
1385 if (!client->data.public_key) {
1386 /* Add client's public key to repository */
1387 if (!silc_server_get_public_key_by_client(server, client, NULL))
1388 silc_skr_add_public_key_simple(server->repository,
1390 SILC_SKR_USAGE_IDENTIFICATION,
1392 client->data.public_key = public_key;
1395 } else if (id_type == SILC_ID_SERVER) {
1396 silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
1398 server_entry = silc_idlist_find_server_by_id(server->local_list,
1399 &server_id, TRUE, NULL);
1400 if (!server_entry) {
1401 server_entry = silc_idlist_find_server_by_id(server->global_list,
1402 &server_id, TRUE, NULL);
1407 server_entry->data.public_key = public_key;
1414 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1416 silc_id_payload_free(idp);
1418 silc_pkcs_public_key_free(public_key);
1420 silc_server_command_reply_free(cmd);
1423 SILC_SERVER_CMD_REPLY_FUNC(list)
1425 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1426 SilcServer server = cmd->server;
1427 SilcStatus status, error;
1429 SilcChannelEntry channel;
1430 SilcIDCacheEntry cache;
1431 unsigned char *tmp, *name, *namec = NULL, *topic;
1432 SilcUInt32 usercount = 0;
1433 SilcBool global_list = FALSE;
1435 COMMAND_CHECK_STATUS;
1437 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1440 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1441 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1442 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1444 SILC_GET32_MSB(usercount, tmp);
1446 namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
1451 /* Add the channel entry if we do not have it already */
1452 channel = silc_idlist_find_channel_by_name(server->local_list,
1455 channel = silc_idlist_find_channel_by_name(server->global_list,
1460 /* If router did not find such channel in its lists then this must
1461 be bogus channel or some router in the net is buggy. */
1462 if (server->server_type != SILC_SERVER)
1465 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1466 SILC_CHANNEL_MODE_NONE,
1467 silc_id_dup(SILC_ID_GET_ID(id),
1469 server->router, NULL, NULL, NULL);
1474 channel->user_count = usercount;
1477 silc_free(channel->topic);
1478 channel->topic = strdup(topic);
1481 /* Pending callbacks are not executed if this was an list entry */
1482 if (status != SILC_STATUS_OK &&
1483 status != SILC_STATUS_LIST_END) {
1484 silc_server_command_reply_free(cmd);
1489 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1492 silc_server_command_reply_free(cmd);
1495 SILC_SERVER_CMD_REPLY_FUNC(watch)
1497 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1498 SilcStatus status, error;
1500 COMMAND_CHECK_STATUS;
1503 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1505 silc_server_command_reply_free(cmd);
1508 SILC_SERVER_CMD_REPLY_FUNC(ping)
1510 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1511 SilcStatus status, error;
1513 COMMAND_CHECK_STATUS;
1516 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1518 silc_server_command_reply_free(cmd);