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_idlist_del_data(client);
156 silc_idlist_del_client(server->global_list, client);
161 /* Caches the received WHOIS information. */
164 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
166 SilcServer server = cmd->server;
167 unsigned char *id_data, *umodes;
168 char *nickname, *username, *realname, *tmp;
169 unsigned char *fingerprint;
171 SilcClientEntry client;
173 char nick[128 + 1], servername[256 + 1], uname[128 + 1];
174 SilcUInt32 mode = 0, len, len2, id_len, flen;
175 const char *hostname, *ip;
177 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
178 NULL, &hostname, &ip, NULL);
180 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
181 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
182 username = silc_argument_get_arg_type(cmd->args, 4, &len);
183 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
184 if (!id_data || !nickname || !username || !realname)
187 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
189 SILC_GET32_MSB(mode, tmp);
191 if (!silc_id_payload_parse_id(id_data, id_len, &id))
194 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
196 /* Check if we have this client cached already. */
198 client = silc_idlist_find_client_by_id(server->local_list,
202 client = silc_idlist_find_client_by_id(server->global_list,
209 /* If router did not find such Client ID in its lists then this must
210 be bogus client or some router in the net is buggy. */
211 if (server->server_type != SILC_SERVER)
214 /* Take hostname out of nick string if it includes it. */
215 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
218 /* We don't have that client anywhere, add it. The client is added
219 to global list since server didn't have it in the lists so it must be
220 global. This will check for valid nickname and username strings. */
221 client = silc_idlist_add_client(server->global_list,
222 strdup(nick), username,
224 silc_id_dup(SILC_ID_GET_ID(id),
226 silc_packet_get_context(cmd->sock),
229 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
233 client->data.status |=
234 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
235 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
237 client->servername = servername[0] ? strdup(servername) : NULL;
239 /* We have the client already, update the data */
241 SILC_LOG_DEBUG(("Updating client data"));
244 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
246 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
249 SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOIS reply "
251 hostname ? hostname : "", nick));
256 silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
257 if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128)) {
258 SILC_LOG_ERROR(("Malformed username '%s' received in WHOIS reply "
260 hostname ? hostname : "", tmp));
265 silc_idcache_update_by_context(global ? server->global_list->clients :
266 server->local_list->clients, client, NULL,
269 silc_free(client->nickname);
270 silc_free(client->username);
271 silc_free(client->userinfo);
272 silc_free(client->servername);
274 client->nickname = strdup(nick);
275 client->username = strdup(username);
276 client->userinfo = strdup(realname);
277 client->servername = servername[0] ? strdup(servername) : NULL;
279 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
280 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
283 /* Save channel list if it was sent to us */
284 if (server->server_type == SILC_SERVER) {
285 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
286 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
288 SilcBufferStruct channels_buf, umodes_buf;
289 silc_buffer_set(&channels_buf, tmp, len);
290 silc_buffer_set(&umodes_buf, umodes, len2);
291 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
294 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
298 if (fingerprint && flen == sizeof(client->data.fingerprint))
299 memcpy(client->data.fingerprint, fingerprint, flen);
301 /* Take Requested Attributes if set. */
302 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
304 silc_free(client->attrs);
305 client->attrs = silc_memdup(tmp, len);
306 client->attrs_len = len;
308 /* Try to take public key from attributes if present and we don't have
309 the key already. Do this only on normal server. Routers do GETKEY
310 for all clients anyway. */
311 if (server->server_type != SILC_ROUTER && !client->data.public_key) {
312 SilcAttributePayload attr;
313 SilcAttributeObjPk pk;
314 unsigned char f[SILC_HASH_MAXLEN];
315 SilcDList attrs = silc_attribute_payload_parse(tmp, len);
317 SILC_LOG_DEBUG(("Take client public key from attributes"));
320 silc_dlist_start(attrs);
321 while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
322 if (silc_attribute_get_attribute(attr) ==
323 SILC_ATTRIBUTE_USER_PUBLIC_KEY) {
325 if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
328 /* Take only SILC public keys */
329 if (strcmp(pk.type, "silc-rsa")) {
335 /* Verify that the server provided fingerprint matches the key */
336 silc_hash_make(server->sha1hash, pk.data, pk.data_len, f);
337 if (memcmp(f, client->data.fingerprint, sizeof(f))) {
343 /* Save the public key. */
344 if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC,
345 pk.data, pk.data_len,
346 &client->data.public_key)) {
352 SILC_LOG_DEBUG(("Saved client public key from attributes"));
354 /* Add client's public key to repository */
355 if (!silc_server_get_public_key_by_client(server, client, NULL))
356 silc_skr_add_public_key_simple(server->repository,
357 client->data.public_key,
358 SILC_SKR_USAGE_IDENTIFICATION,
367 silc_attribute_payload_list_free(attrs);
375 /* Handle requested attributes reply in WHOIS from client */
378 silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd)
382 SilcClientEntry client = silc_packet_get_context(cmd->sock);
384 /* Take Requested Attributes if set. */
385 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
387 silc_free(client->attrs);
388 client->attrs = silc_memdup(tmp, len);
389 client->attrs_len = len;
392 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
397 /* Reiceved reply for WHOIS command. We sent the whois request to our
398 primary router, if we are normal server, and thus has now received reply
399 to the command. We will figure out what client originally sent us the
400 command and will send the reply to it. If we are router we will figure
401 out who server sent us the command and send reply to that one. */
403 SILC_SERVER_CMD_REPLY_FUNC(whois)
405 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
406 SilcIDListData idata = silc_packet_get_context(cmd->sock);
407 SilcStatus status, error;
409 COMMAND_CHECK_STATUS;
411 if (idata->conn_type != SILC_CONN_CLIENT) {
412 if (!silc_server_command_reply_whois_save(cmd))
415 if (!silc_server_command_reply_whois_save_client(cmd))
419 /* Pending callbacks are not executed if this was an list entry */
420 if (status != SILC_STATUS_OK &&
421 status != SILC_STATUS_LIST_END) {
422 silc_server_command_reply_free(cmd);
427 silc_server_command_process_error(cmd, error);
428 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
429 silc_server_command_reply_free(cmd);
433 silc_server_command_process_error(cmd, error);
434 silc_server_command_reply_free(cmd);
437 /* Caches the received WHOWAS information for a short period of time. */
440 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
442 SilcServer server = cmd->server;
443 SilcUInt32 len, id_len;
444 unsigned char *id_data;
445 char *nickname, *username, *realname;
447 SilcClientEntry client;
448 SilcIDCacheEntry cache = NULL;
449 char nick[128 + 1], servername[256 + 1], uname[128 + 1];
451 const char *hostname, *ip;
453 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
454 NULL, &hostname, &ip, NULL);
456 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
457 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
458 username = silc_argument_get_arg_type(cmd->args, 4, &len);
459 if (!id_data || !nickname || !username)
462 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
464 if (!silc_id_payload_parse_id(id_data, id_len, &id))
467 /* Check if we have this client cached already. */
469 client = silc_idlist_find_client_by_id(server->local_list,
473 client = silc_idlist_find_client_by_id(server->global_list,
480 /* If router did not find such Client ID in its lists then this must
481 be bogus client or some router in the net is buggy. */
482 if (server->server_type != SILC_SERVER)
485 /* Take hostname out of nick string if it includes it. */
486 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
489 /* We don't have that client anywhere, add it. The client is added
490 to global list since server didn't have it in the lists so it must be
492 client = silc_idlist_add_client(server->global_list,
493 strdup(nick), username,
495 silc_id_dup(SILC_ID_GET_ID(id),
497 silc_packet_get_context(cmd->sock), NULL);
499 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
503 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
504 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
505 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
506 client->servername = servername[0] ? strdup(servername) : NULL;
508 /* We have the client already, update the data */
511 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
513 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
516 SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOWAS reply "
518 hostname ? hostname : "", nick));
523 silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
524 if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128))
527 silc_free(client->nickname);
528 silc_free(client->username);
529 silc_free(client->servername);
531 client->nickname = strdup(nick);
532 client->username = strdup(username);
533 client->servername = servername[0] ? strdup(servername) : NULL;
534 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
535 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
537 /* Remove the old cache entry and create a new one */
538 silc_idcache_del_by_context(global ? server->global_list->clients :
539 server->local_list->clients, client, NULL);
540 silc_idcache_add(global ? server->global_list->clients :
541 server->local_list->clients, nickname, client->id,
545 /* If client is global and is not on any channel then add that we'll
546 expire the entry after a while. */
548 silc_idlist_find_client_by_id(server->global_list, client->id,
550 if (!silc_hash_table_count(client->channels))
551 silc_dlist_add(server->expired_clients, client);
557 /* Received reply for WHOWAS command. Cache the client information only for
558 a short period of time. */
560 SILC_SERVER_CMD_REPLY_FUNC(whowas)
562 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
563 SilcStatus status, error;
565 COMMAND_CHECK_STATUS;
567 if (!silc_server_command_reply_whowas_save(cmd))
570 /* Pending callbacks are not executed if this was an list entry */
571 if (status != SILC_STATUS_OK &&
572 status != SILC_STATUS_LIST_END) {
573 silc_server_command_reply_free(cmd);
578 silc_server_command_process_error(cmd, error);
579 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
580 silc_server_command_reply_free(cmd);
584 silc_server_command_process_error(cmd, error);
585 silc_server_command_reply_free(cmd);
588 /* Caches the received IDENTIFY information. */
591 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
593 SilcServer server = cmd->server;
594 SilcUInt32 len, id_len;
595 unsigned char *id_data;
597 SilcClientID client_id;
598 SilcServerID server_id;
599 SilcChannelID*channel_id;
600 SilcClientEntry client;
601 SilcServerEntry server_entry;
602 SilcChannelEntry channel;
605 SilcIDPayload idp = NULL;
608 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
611 idp = silc_id_payload_parse(id_data, id_len);
615 name = silc_argument_get_arg_type(cmd->args, 3, &len);
616 info = silc_argument_get_arg_type(cmd->args, 4, &len);
618 id_type = silc_id_payload_get_type(idp);
622 if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
625 SILC_LOG_DEBUG(("Received client information"));
627 client = silc_idlist_find_client_by_id(server->local_list,
628 &client_id, FALSE, NULL);
630 client = silc_idlist_find_client_by_id(server->global_list, &client_id,
635 /* If router did not find such Client ID in its lists then this must
636 be bogus client or some router in the net is buggy. */
637 if (server->server_type != SILC_SERVER)
642 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
644 /* We don't have that client anywhere, add it. The client is added
645 to global list since server didn't have it in the lists so it must be
647 client = silc_idlist_add_client(server->global_list,
648 nick[0] ? nick : NULL, info, NULL,
649 silc_id_dup(&client_id, SILC_ID_CLIENT),
650 silc_packet_get_context(cmd->sock),
653 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
657 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
658 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
659 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
661 /* We have the client already, update the data */
663 SILC_LOG_DEBUG(("Updating client data"));
667 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
670 name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
673 SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY "
678 /* Remove the old cache entry */
679 silc_idcache_del_by_context(global ? server->global_list->clients :
680 server->local_list->clients, client, NULL);
682 silc_free(client->nickname);
683 client->nickname = strdup(nick);
685 /* Add new cache entry */
686 silc_idcache_add(global ? server->global_list->clients :
687 server->local_list->clients, name, client->id,
692 silc_free(client->username);
693 client->username = strdup(info);
696 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
697 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
706 if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
709 SILC_LOG_DEBUG(("Received server information"));
711 server_entry = silc_idlist_find_server_by_id(server->local_list,
712 &server_id, FALSE, NULL);
714 server_entry = silc_idlist_find_server_by_id(server->global_list,
715 &server_id, FALSE, NULL);
717 /* If router did not find such Server ID in its lists then this must
718 be bogus server or some router in the net is buggy. */
719 if (server->server_type != SILC_SERVER)
722 /* We don't have that server anywhere, add it. */
723 server_entry = silc_idlist_add_server(server->global_list,
725 silc_id_dup(&server_id,
728 SILC_PRIMARY_ROUTE(server));
732 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
733 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
734 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
739 case SILC_ID_CHANNEL:
743 if (!silc_id_payload_get_id(idp, &channel_id, sizeof(channel_id)))
746 SILC_LOG_DEBUG(("Received channel information"));
748 /* Check channel name */
749 info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
754 channel = silc_idlist_find_channel_by_name(server->local_list,
757 channel = silc_idlist_find_channel_by_name(server->global_list,
760 /* If router did not find such Channel ID in its lists then this must
761 be bogus channel or some router in the net is buggy. */
762 if (server->server_type != SILC_SERVER) {
767 /* We don't have that channel anywhere, add it. */
768 channel = silc_idlist_add_channel(server->global_list, strdup(name),
769 SILC_CHANNEL_MODE_NONE,
770 silc_id_dup(&channel_id,
772 server->router, NULL, NULL, 0);
783 silc_id_payload_free(idp);
787 silc_id_payload_free(idp);
791 /* Received reply for forwarded IDENTIFY command. We have received the
792 requested identify information now and we will cache it. After this we
793 will call the pending command so that the requestee gets the information
796 SILC_SERVER_CMD_REPLY_FUNC(identify)
798 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
799 SilcStatus status, error;
801 COMMAND_CHECK_STATUS;
803 if (!silc_server_command_reply_identify_save(cmd))
806 /* Pending callbacks are not executed if this was an list entry */
807 if (status != SILC_STATUS_OK &&
808 status != SILC_STATUS_LIST_END) {
809 silc_server_command_reply_free(cmd);
814 silc_server_command_process_error(cmd, error);
815 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
816 silc_server_command_reply_free(cmd);
820 silc_server_command_process_error(cmd, error);
821 silc_server_command_reply_free(cmd);
824 /* Received reply fro INFO command. Cache the server and its information */
826 SILC_SERVER_CMD_REPLY_FUNC(info)
828 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
829 SilcServer server = cmd->server;
830 SilcStatus status, error;
831 SilcServerEntry entry;
834 unsigned char *tmp, *name;
836 COMMAND_CHECK_STATUS;
839 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
843 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
847 entry = silc_idlist_find_server_by_id(server->local_list,
851 entry = silc_idlist_find_server_by_id(server->global_list,
855 /* Add the server to global list */
856 entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
857 silc_id_dup(SILC_ID_GET_ID(id),
859 silc_packet_get_context(cmd->sock),
864 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
868 /* Get the info string */
869 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
873 entry->server_info = tmp ? strdup(tmp) : NULL;
876 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
878 silc_server_command_reply_free(cmd);
881 /* Received reply fro MOTD command. */
883 SILC_SERVER_CMD_REPLY_FUNC(motd)
885 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
886 SilcServer server = cmd->server;
887 SilcStatus status, error;
888 SilcServerEntry entry = NULL;
893 COMMAND_CHECK_STATUS;
896 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
899 entry = silc_idlist_find_server_by_id(server->local_list,
903 entry = silc_idlist_find_server_by_id(server->global_list,
909 /* If router did not find such Server ID in its lists then this must
910 be bogus client or some router in the net is buggy. */
911 if (server->server_type != SILC_SERVER)
915 cmd->server->stat.commands_sent++;
917 /* entry isn't known so we IDENTIFY it. otherwise the
918 silc_server_command_motd won't know about it and tell
919 the client that there is no such server */
920 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
921 buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
922 ++server->cmd_ident, 5,
923 1, NULL, 0, 2, NULL, 0,
924 3, NULL, 0, 4, NULL, 0,
926 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
927 SILC_PACKET_COMMAND, 0, buffer->data,
928 silc_buffer_len(buffer));
929 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
931 silc_server_command_reply_motd,
933 silc_buffer_free(buffer);
939 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
946 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
948 silc_server_command_reply_free(cmd);
954 /* Received reply for forwarded JOIN command. Router has created or joined
955 the client to the channel. We save some channel information locally
958 SILC_SERVER_CMD_REPLY_FUNC(join)
960 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
961 SilcServer server = cmd->server;
962 SilcIDCacheEntry cache = NULL;
963 SilcStatus status, error;
965 SilcChannelEntry entry;
966 SilcHmac hmac = NULL;
967 SilcUInt32 len, list_count;
968 char *channel_name, *channel_namec = NULL, *tmp;
969 SilcUInt32 mode, created;
970 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
971 SilcPublicKey founder_key = NULL;
973 COMMAND_CHECK_STATUS;
975 /* Get channel name */
976 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
981 if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id, NULL))
985 if (!silc_argument_get_decoded(cmd->args, 4, SILC_ARGUMENT_ID, &id2, NULL))
989 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
992 SILC_GET32_MSB(mode, tmp);
994 /* Get created boolean value */
995 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
998 SILC_GET32_MSB(created, tmp);
999 if (created != 0 && created != 1)
1002 /* Get channel key */
1003 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
1005 keyp = silc_buffer_alloc(len);
1006 silc_buffer_pull_tail(keyp, silc_buffer_truelen(keyp));
1007 silc_buffer_put(keyp, tmp, len);
1011 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1013 if (!silc_hmac_alloc(tmp, NULL, &hmac))
1017 /* Get the list count */
1018 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1021 SILC_GET32_MSB(list_count, tmp);
1023 /* Get Client ID list */
1024 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1028 client_id_list = silc_buffer_alloc(len);
1029 silc_buffer_pull_tail(client_id_list, len);
1030 silc_buffer_put(client_id_list, tmp, len);
1032 /* Get client mode list */
1033 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1037 client_mode_list = silc_buffer_alloc(len);
1038 silc_buffer_pull_tail(client_mode_list, len);
1039 silc_buffer_put(client_mode_list, tmp, len);
1041 /* Get founder key */
1042 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1044 silc_public_key_payload_decode(tmp, len, &founder_key);
1046 /* See whether we already have the channel. */
1047 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
1048 SILC_STRING_UTF8, 256, NULL);
1051 entry = silc_idlist_find_channel_by_name(server->local_list,
1052 channel_namec, &cache);
1054 /* Add new channel */
1056 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1057 (created == 0 ? "existing" : "created"), channel_name,
1058 silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL)));
1060 /* If the channel is found from global list we must move it to the
1062 entry = silc_idlist_find_channel_by_name(server->global_list,
1063 channel_namec, &cache);
1065 silc_idlist_del_channel(server->global_list, entry);
1067 /* Add the channel to our local list. */
1068 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1069 SILC_CHANNEL_MODE_NONE,
1070 silc_id_dup(SILC_ID_GET_ID(id),
1072 server->router, NULL, NULL, hmac);
1077 server->stat.my_channels++;
1078 server->stat.channels++;
1080 /* The entry exists. */
1082 /* If ID has changed, then update it to the cache too. */
1083 if (!SILC_ID_CHANNEL_COMPARE(entry->id, SILC_ID_GET_ID(id)))
1084 silc_idlist_replace_channel_id(server->local_list, entry->id,
1085 SILC_ID_GET_ID(id));
1087 entry->disabled = FALSE;
1089 /* Remove the founder auth data if the mode is not set but we have
1090 them in the entry */
1091 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1092 silc_pkcs_public_key_free(entry->founder_key);
1093 entry->founder_key = NULL;
1098 if (entry->founder_key)
1099 silc_pkcs_public_key_free(entry->founder_key);
1100 entry->founder_key = founder_key;
1104 if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1105 silc_free(entry->hmac_name);
1106 entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1109 /* Get the ban list */
1110 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1111 if (tmp && len > 2) {
1112 SilcArgumentPayload iargs;
1114 SILC_GET16_MSB(iargc, tmp);
1115 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1117 /* Delete old ban list */
1118 if (entry->ban_list)
1119 silc_hash_table_free(entry->ban_list);
1121 silc_hash_table_alloc(0, silc_hash_ptr,
1123 silc_server_inviteban_destruct, entry, TRUE);
1125 /* Add new ban list */
1126 silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1127 silc_argument_payload_free(iargs);
1131 /* Get the invite list */
1132 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1133 if (tmp && len > 2) {
1134 SilcArgumentPayload iargs;
1136 SILC_GET16_MSB(iargc, tmp);
1137 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1139 /* Delete old invite list */
1140 if (entry->invite_list)
1141 silc_hash_table_free(entry->invite_list);
1142 entry->invite_list =
1143 silc_hash_table_alloc(0, silc_hash_ptr,
1145 silc_server_inviteban_destruct, entry, TRUE);
1147 /* Add new invite list */
1148 silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1149 silc_argument_payload_free(iargs);
1154 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1156 silc_free(entry->topic);
1157 entry->topic = strdup(tmp);
1160 /* Get channel public key list */
1161 tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1162 if (tmp && server->server_type != SILC_ROUTER)
1163 silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1165 /* The the user limit */
1166 tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1167 if (tmp && len == 4)
1168 SILC_GET32_MSB(entry->user_limit, tmp);
1170 /* If channel was not created we know there is global users on the
1172 entry->global_users = (created == 0 ? TRUE : FALSE);
1174 /* If channel was just created the mask must be zero */
1175 if (!entry->global_users && mode)
1178 /* Save channel mode */
1181 /* Save channel key */
1183 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1184 silc_server_save_channel_key(server, keyp, entry);
1185 silc_buffer_free(keyp);
1188 /* Save the users to the channel */
1189 silc_server_save_users_on_channel(server, cmd->sock, entry,
1190 SILC_ID_GET_ID(id2), client_id_list,
1191 client_mode_list, list_count);
1192 entry->users_resolved = TRUE;
1195 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1197 silc_free(channel_namec);
1199 silc_hmac_free(hmac);
1200 silc_server_command_reply_free(cmd);
1203 silc_pkcs_public_key_free(founder_key);
1205 silc_buffer_free(client_id_list);
1206 if (client_mode_list)
1207 silc_buffer_free(client_mode_list);
1210 /* Received reply to STATS command. */
1212 SILC_SERVER_CMD_REPLY_FUNC(stats)
1214 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1215 SilcServer server = cmd->server;
1216 SilcStatus status, error;
1219 SilcBufferStruct buf;
1221 COMMAND_CHECK_STATUS;
1223 /* Get statistics structure */
1224 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1225 if (server->server_type != SILC_ROUTER && tmp) {
1226 silc_buffer_set(&buf, tmp, tmp_len);
1227 silc_buffer_unformat(&buf,
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(NULL),
1234 SILC_STR_UI_INT(&server->stat.cell_clients),
1235 SILC_STR_UI_INT(&server->stat.cell_channels),
1236 SILC_STR_UI_INT(&server->stat.cell_servers),
1237 SILC_STR_UI_INT(&server->stat.clients),
1238 SILC_STR_UI_INT(&server->stat.channels),
1239 SILC_STR_UI_INT(&server->stat.servers),
1240 SILC_STR_UI_INT(&server->stat.routers),
1241 SILC_STR_UI_INT(&server->stat.server_ops),
1242 SILC_STR_UI_INT(&server->stat.router_ops),
1247 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1249 silc_server_command_reply_free(cmd);
1252 SILC_SERVER_CMD_REPLY_FUNC(users)
1254 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1255 SilcServer server = cmd->server;
1256 SilcStatus status, error;
1257 SilcChannelEntry channel;
1259 SilcBuffer client_id_list;
1260 SilcBuffer client_mode_list;
1263 SilcUInt32 list_count;
1265 COMMAND_CHECK_STATUS;
1267 /* Get channel ID */
1268 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1271 /* Get channel entry */
1272 channel = silc_idlist_find_channel_by_id(server->local_list,
1273 SILC_ID_GET_ID(id), NULL);
1275 channel = silc_idlist_find_channel_by_id(server->global_list,
1276 SILC_ID_GET_ID(id), NULL);
1280 if (server->server_type != SILC_SERVER)
1283 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1284 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1285 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1286 1, 5, idp->data, silc_buffer_len(idp));
1287 silc_buffer_free(idp);
1289 /* Register pending command callback. After we've received the channel
1290 information we will reprocess this command reply by re-calling this
1291 USERS command reply callback. */
1292 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1294 silc_server_command_reply_users, cmd);
1299 /* Get the list count */
1300 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1303 SILC_GET32_MSB(list_count, tmp);
1305 /* Get Client ID list */
1306 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1310 client_id_list = silc_buffer_alloc(tmp_len);
1311 silc_buffer_pull_tail(client_id_list, tmp_len);
1312 silc_buffer_put(client_id_list, tmp, tmp_len);
1314 /* Get client mode list */
1315 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1319 client_mode_list = silc_buffer_alloc(tmp_len);
1320 silc_buffer_pull_tail(client_mode_list, tmp_len);
1321 silc_buffer_put(client_mode_list, tmp, tmp_len);
1323 /* Save the users to the channel */
1324 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1325 client_id_list, client_mode_list,
1328 channel->global_users = silc_server_channel_has_global(channel);
1329 channel->users_resolved = TRUE;
1331 silc_buffer_free(client_id_list);
1332 silc_buffer_free(client_mode_list);
1335 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1337 silc_server_command_reply_free(cmd);
1340 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1342 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1343 SilcServer server = cmd->server;
1344 SilcStatus status, error;
1345 SilcClientEntry client = NULL;
1346 SilcServerEntry server_entry = NULL;
1347 SilcClientID client_id;
1348 SilcServerID server_id;
1351 SilcIDPayload idp = NULL;
1353 SilcPublicKey public_key = NULL;
1355 COMMAND_CHECK_STATUS;
1357 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1360 idp = silc_id_payload_parse(tmp, len);
1364 /* Get the public key payload */
1365 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1369 /* Decode the public key payload */
1370 if (!silc_public_key_payload_decode(tmp, len, &public_key))
1373 id_type = silc_id_payload_get_type(idp);
1374 if (id_type == SILC_ID_CLIENT) {
1375 silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
1377 client = silc_idlist_find_client_by_id(server->local_list, &client_id,
1380 client = silc_idlist_find_client_by_id(server->global_list,
1381 &client_id, TRUE, NULL);
1386 if (!client->data.public_key) {
1387 /* Add client's public key to repository */
1388 if (!silc_server_get_public_key_by_client(server, client, NULL))
1389 silc_skr_add_public_key_simple(server->repository,
1391 SILC_SKR_USAGE_IDENTIFICATION,
1393 client->data.public_key = public_key;
1396 } else if (id_type == SILC_ID_SERVER) {
1397 silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
1399 server_entry = silc_idlist_find_server_by_id(server->local_list,
1400 &server_id, TRUE, NULL);
1401 if (!server_entry) {
1402 server_entry = silc_idlist_find_server_by_id(server->global_list,
1403 &server_id, TRUE, NULL);
1408 server_entry->data.public_key = public_key;
1415 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1417 silc_id_payload_free(idp);
1419 silc_pkcs_public_key_free(public_key);
1421 silc_server_command_reply_free(cmd);
1424 SILC_SERVER_CMD_REPLY_FUNC(list)
1426 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1427 SilcServer server = cmd->server;
1428 SilcStatus status, error;
1430 SilcChannelEntry channel;
1431 SilcIDCacheEntry cache;
1432 unsigned char *tmp, *name, *namec = NULL, *topic;
1433 SilcUInt32 usercount = 0;
1434 SilcBool global_list = FALSE;
1436 COMMAND_CHECK_STATUS;
1438 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1441 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1442 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1443 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1445 SILC_GET32_MSB(usercount, tmp);
1447 namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
1452 /* Add the channel entry if we do not have it already */
1453 channel = silc_idlist_find_channel_by_name(server->local_list,
1456 channel = silc_idlist_find_channel_by_name(server->global_list,
1461 /* If router did not find such channel in its lists then this must
1462 be bogus channel or some router in the net is buggy. */
1463 if (server->server_type != SILC_SERVER)
1466 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1467 SILC_CHANNEL_MODE_NONE,
1468 silc_id_dup(SILC_ID_GET_ID(id),
1470 server->router, NULL, NULL, NULL);
1475 channel->user_count = usercount;
1478 silc_free(channel->topic);
1479 channel->topic = strdup(topic);
1482 /* Pending callbacks are not executed if this was an list entry */
1483 if (status != SILC_STATUS_OK &&
1484 status != SILC_STATUS_LIST_END) {
1485 silc_server_command_reply_free(cmd);
1490 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1493 silc_server_command_reply_free(cmd);
1496 SILC_SERVER_CMD_REPLY_FUNC(watch)
1498 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1499 SilcStatus status, error;
1501 COMMAND_CHECK_STATUS;
1504 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1506 silc_server_command_reply_free(cmd);
1509 SILC_SERVER_CMD_REPLY_FUNC(ping)
1511 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1512 SilcStatus status, error;
1514 COMMAND_CHECK_STATUS;
1517 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1519 silc_server_command_reply_free(cmd);