5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2009 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "serverincludes.h"
22 #include "server_internal.h"
23 #include "command_reply.h"
25 /* All functions that call the COMMAND_CHECK_STATUS macros must have
26 out: and err: goto labels. */
28 #define COMMAND_CHECK_STATUS \
30 SILC_LOG_DEBUG(("Start")); \
31 if (!silc_command_get_status(cmd->payload, &status, &error)) { \
32 if (SILC_STATUS_IS_ERROR(status)) \
34 if (status == SILC_STATUS_LIST_END) \
40 /* Server command reply list. Not all commands have reply function as
41 they are never sent by server. More maybe added later if need appears. */
42 SilcServerCommandReply silc_command_reply_list[] =
44 SILC_SERVER_CMD_REPLY(whois, WHOIS),
45 SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
46 SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
47 SILC_SERVER_CMD_REPLY(info, INFO),
48 SILC_SERVER_CMD_REPLY(motd, MOTD),
49 SILC_SERVER_CMD_REPLY(join, JOIN),
50 SILC_SERVER_CMD_REPLY(stats, STATS),
51 SILC_SERVER_CMD_REPLY(users, USERS),
52 SILC_SERVER_CMD_REPLY(getkey, GETKEY),
53 SILC_SERVER_CMD_REPLY(list, LIST),
54 SILC_SERVER_CMD_REPLY(watch, WATCH),
55 SILC_SERVER_CMD_REPLY(ping, PING),
60 /* Process received command reply. */
62 void silc_server_command_reply_process(SilcServer server,
63 SilcPacketStream sock,
66 SilcIDListData idata = silc_packet_get_context(sock);
67 SilcServerCommandReply *cmd;
68 SilcServerCommandReplyContext ctx;
69 SilcCommandPayload payload;
72 SILC_LOG_DEBUG(("Start"));
74 /* Get command reply payload from packet */
75 payload = silc_command_payload_parse(buffer->data, silc_buffer_len(buffer));
77 /* Silently ignore bad reply packet */
78 SILC_LOG_DEBUG(("Bad command reply packet"));
82 /* Allocate command reply context. This must be free'd by the
83 command reply routine receiving it. */
84 ctx = silc_calloc(1, sizeof(*ctx));
87 ctx->payload = payload;
88 ctx->args = silc_command_get_args(ctx->payload);
89 ctx->ident = silc_command_get_ident(ctx->payload);
90 command = silc_command_get(ctx->payload);
91 silc_packet_stream_ref(sock);
93 /* Client is not allowed to send reply to all commands */
94 if (idata->conn_type == SILC_CONN_CLIENT &&
95 command != SILC_COMMAND_WHOIS) {
96 silc_server_command_reply_free(ctx);
100 /* Check for pending commands and mark to be exeucted */
102 silc_server_command_pending_check(server, command,
103 ctx->ident, &ctx->callbacks_count);
105 /* Execute command reply */
106 for (cmd = silc_command_reply_list; cmd->cb; cmd++)
107 if (cmd->cmd == command)
110 if (cmd == NULL || !cmd->cb) {
111 silc_server_command_reply_free(ctx);
118 /* Free command reply context and its internals. */
120 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
123 silc_command_payload_free(cmd->payload);
125 silc_packet_stream_unref(cmd->sock);
126 silc_free(cmd->callbacks);
132 silc_server_command_process_error(SilcServerCommandReplyContext cmd,
135 SilcServer server = cmd->server;
136 SilcIDListData idata = silc_packet_get_context(cmd->sock);
138 /* If we received notify for invalid ID we'll remove the ID if we
140 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
141 idata->conn_type == SILC_CONN_ROUTER) {
142 SilcClientEntry client;
144 if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id,
146 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
147 "the entry from cache"));
148 client = silc_idlist_find_client_by_id(server->global_list,
149 SILC_ID_GET_ID(id), FALSE, NULL);
153 silc_server_remove_from_channels(server, NULL, client, TRUE,
155 silc_dlist_del(server->expired_clients, client);
156 silc_idlist_del_data(client);
157 silc_idlist_del_client(server->global_list, client);
162 /* Caches the received WHOIS information. */
165 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
167 SilcServer server = cmd->server;
168 unsigned char *id_data, *umodes;
169 char *nickname, *username, *realname, *tmp;
170 unsigned char *fingerprint;
172 SilcClientEntry client;
174 char nick[128 + 1], servername[256 + 1], uname[128 + 1];
175 SilcUInt32 mode = 0, len, len2, id_len, flen;
176 const char *hostname, *ip;
178 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
179 NULL, &hostname, &ip, NULL);
181 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
182 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
183 username = silc_argument_get_arg_type(cmd->args, 4, &len);
184 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
185 if (!id_data || !nickname || !username || !realname)
188 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
190 SILC_GET32_MSB(mode, tmp);
192 if (!silc_id_payload_parse_id(id_data, id_len, &id))
195 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
197 /* Check if we have this client cached already. */
199 client = silc_idlist_find_client_by_id(server->local_list,
203 client = silc_idlist_find_client_by_id(server->global_list,
210 /* If router did not find such Client ID in its lists then this must
211 be bogus client or some router in the net is buggy. */
212 if (server->server_type != SILC_SERVER)
215 /* Take hostname out of nick string if it includes it. */
216 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
219 /* We don't have that client anywhere, add it. The client is added
220 to global list since server didn't have it in the lists so it must be
221 global. This will check for valid nickname and username strings. */
222 client = silc_idlist_add_client(server->global_list,
223 strdup(nick), username,
225 silc_id_dup(SILC_ID_GET_ID(id),
227 silc_packet_get_context(cmd->sock),
230 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
234 client->data.status |=
235 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
236 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
238 client->servername = servername[0] ? strdup(servername) : NULL;
240 SILC_LOG_DEBUG(("stat.clients %d->%d", server->stat.clients,
241 server->stat.clients + 1));
242 server->stat.clients++;
244 /* We have the client already, update the data */
246 SILC_LOG_DEBUG(("Updating client data"));
249 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
251 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
254 SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOIS reply "
256 hostname ? hostname : "", nick));
261 silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
262 if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128)) {
263 SILC_LOG_ERROR(("Malformed username '%s' received in WHOIS reply "
265 hostname ? hostname : "", tmp));
270 silc_idcache_update_by_context(global ? server->global_list->clients :
271 server->local_list->clients, client, NULL,
274 silc_free(client->nickname);
275 silc_free(client->username);
276 silc_free(client->userinfo);
277 silc_free(client->servername);
279 client->nickname = strdup(nick);
280 client->username = strdup(username);
281 client->userinfo = strdup(realname);
282 client->servername = servername[0] ? strdup(servername) : NULL;
284 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
285 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
288 /* Save channel list if it was sent to us */
289 if (server->server_type == SILC_SERVER) {
290 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
291 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
293 SilcBufferStruct channels_buf, umodes_buf;
294 silc_buffer_set(&channels_buf, tmp, len);
295 silc_buffer_set(&umodes_buf, umodes, len2);
296 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
299 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
303 if (fingerprint && flen == sizeof(client->data.fingerprint))
304 memcpy(client->data.fingerprint, fingerprint, flen);
306 /* Take Requested Attributes if set. */
307 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
309 silc_free(client->attrs);
310 client->attrs = silc_memdup(tmp, len);
311 client->attrs_len = len;
313 /* Try to take public key from attributes if present and we don't have
314 the key already. Do this only on normal server. Routers do GETKEY
315 for all clients anyway. */
316 if (server->server_type != SILC_ROUTER && !client->data.public_key) {
317 SilcAttributePayload attr;
318 SilcAttributeObjPk pk;
319 unsigned char f[SILC_HASH_MAXLEN];
320 SilcDList attrs = silc_attribute_payload_parse(tmp, len);
322 SILC_LOG_DEBUG(("Take client public key from attributes"));
325 silc_dlist_start(attrs);
326 while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
327 if (silc_attribute_get_attribute(attr) ==
328 SILC_ATTRIBUTE_USER_PUBLIC_KEY) {
330 if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
333 /* Take only SILC public keys */
334 if (strcmp(pk.type, "silc-rsa")) {
340 /* Verify that the server provided fingerprint matches the key */
341 silc_hash_make(server->sha1hash, pk.data, pk.data_len, f);
342 if (memcmp(f, client->data.fingerprint, sizeof(f))) {
348 /* Save the public key. */
349 if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC,
350 pk.data, pk.data_len,
351 &client->data.public_key)) {
357 SILC_LOG_DEBUG(("Saved client public key from attributes"));
359 /* Add client's public key to repository */
360 if (!silc_server_get_public_key_by_client(server, client, NULL))
361 silc_skr_add_public_key_simple(server->repository,
362 client->data.public_key,
363 SILC_SKR_USAGE_IDENTIFICATION,
372 silc_attribute_payload_list_free(attrs);
380 /* Handle requested attributes reply in WHOIS from client */
383 silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd)
387 SilcClientEntry client = silc_packet_get_context(cmd->sock);
389 /* Take Requested Attributes if set. */
390 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
392 silc_free(client->attrs);
393 client->attrs = silc_memdup(tmp, len);
394 client->attrs_len = len;
397 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
402 /* Reiceved reply for WHOIS command. We sent the whois request to our
403 primary router, if we are normal server, and thus has now received reply
404 to the command. We will figure out what client originally sent us the
405 command and will send the reply to it. If we are router we will figure
406 out who server sent us the command and send reply to that one. */
408 SILC_SERVER_CMD_REPLY_FUNC(whois)
410 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
411 SilcIDListData idata = silc_packet_get_context(cmd->sock);
412 SilcStatus status, error;
414 COMMAND_CHECK_STATUS;
416 if (idata->conn_type != SILC_CONN_CLIENT) {
417 if (!silc_server_command_reply_whois_save(cmd))
420 if (!silc_server_command_reply_whois_save_client(cmd))
424 /* Pending callbacks are not executed if this was an list entry */
425 if (status != SILC_STATUS_OK &&
426 status != SILC_STATUS_LIST_END) {
427 silc_server_command_reply_free(cmd);
432 silc_server_command_process_error(cmd, error);
433 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
434 silc_server_command_reply_free(cmd);
438 silc_server_command_process_error(cmd, error);
439 silc_server_command_reply_free(cmd);
442 /* Caches the received WHOWAS information for a short period of time. */
445 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
447 SilcServer server = cmd->server;
448 SilcUInt32 len, id_len;
449 unsigned char *id_data;
450 char *nickname, *username, *realname;
452 SilcClientEntry client;
453 SilcIDCacheEntry cache = NULL;
454 char nick[128 + 1], servername[256 + 1], uname[128 + 1];
456 const char *hostname, *ip;
458 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
459 NULL, &hostname, &ip, NULL);
461 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
462 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
463 username = silc_argument_get_arg_type(cmd->args, 4, &len);
464 if (!id_data || !nickname || !username)
467 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
469 if (!silc_id_payload_parse_id(id_data, id_len, &id))
472 /* Check if we have this client cached already. */
474 client = silc_idlist_find_client_by_id(server->local_list,
478 client = silc_idlist_find_client_by_id(server->global_list,
485 /* If router did not find such Client ID in its lists then this must
486 be bogus client or some router in the net is buggy. */
487 if (server->server_type != SILC_SERVER)
490 /* Take hostname out of nick string if it includes it. */
491 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
494 /* We don't have that client anywhere, add it. The client is added
495 to global list since server didn't have it in the lists so it must be
497 client = silc_idlist_add_client(server->global_list,
498 strdup(nick), username,
500 silc_id_dup(SILC_ID_GET_ID(id),
502 silc_packet_get_context(cmd->sock), NULL);
504 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
508 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
509 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
510 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
511 client->servername = servername[0] ? strdup(servername) : NULL;
513 /* We have the client already, update the data */
516 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
518 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
521 SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOWAS reply "
523 nick, hostname ? hostname : ""));
528 silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
529 if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128))
532 silc_free(client->nickname);
533 silc_free(client->username);
534 silc_free(client->servername);
536 client->nickname = strdup(nick);
537 client->username = strdup(username);
538 client->servername = servername[0] ? strdup(servername) : NULL;
539 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
540 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
541 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
543 /* Update cache entry */
544 silc_idcache_update_by_context(global ? server->global_list->clients :
545 server->local_list->clients, client, NULL,
549 /* If client is global and is not on any channel then add that we'll
550 expire the entry after a while. */
552 client = silc_idlist_find_client_by_id(server->global_list, client->id,
554 if (client && !silc_hash_table_count(client->channels)) {
555 client->data.created = silc_time();
556 silc_dlist_del(server->expired_clients, client);
557 silc_dlist_add(server->expired_clients, client);
564 /* Received reply for WHOWAS command. Cache the client information only for
565 a short period of time. */
567 SILC_SERVER_CMD_REPLY_FUNC(whowas)
569 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
570 SilcStatus status, error;
572 COMMAND_CHECK_STATUS;
574 if (!silc_server_command_reply_whowas_save(cmd))
577 /* Pending callbacks are not executed if this was an list entry */
578 if (status != SILC_STATUS_OK &&
579 status != SILC_STATUS_LIST_END) {
580 silc_server_command_reply_free(cmd);
585 silc_server_command_process_error(cmd, error);
586 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
587 silc_server_command_reply_free(cmd);
591 silc_server_command_process_error(cmd, error);
592 silc_server_command_reply_free(cmd);
595 /* Caches the received IDENTIFY information. */
598 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
600 SilcServer server = cmd->server;
601 SilcUInt32 len, id_len;
602 unsigned char *id_data;
604 SilcClientID client_id;
605 SilcServerID server_id;
606 SilcChannelID channel_id;
607 SilcClientEntry client;
608 SilcServerEntry server_entry;
609 SilcChannelEntry channel;
612 SilcIDPayload idp = NULL;
615 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
618 idp = silc_id_payload_parse(id_data, id_len);
622 name = silc_argument_get_arg_type(cmd->args, 3, &len);
623 info = silc_argument_get_arg_type(cmd->args, 4, &len);
625 id_type = silc_id_payload_get_type(idp);
629 if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
632 SILC_LOG_DEBUG(("Received client information"));
634 client = silc_idlist_find_client_by_id(server->local_list,
635 &client_id, FALSE, NULL);
637 client = silc_idlist_find_client_by_id(server->global_list, &client_id,
642 /* If router did not find such Client ID in its lists then this must
643 be bogus client or some router in the net is buggy. */
644 if (server->server_type != SILC_SERVER)
649 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
651 /* We don't have that client anywhere, add it. The client is added
652 to global list since server didn't have it in the lists so it must be
654 client = silc_idlist_add_client(server->global_list,
655 nick[0] ? strdup(nick) : NULL,
656 info ? strdup(info) : NULL, NULL,
657 silc_id_dup(&client_id, SILC_ID_CLIENT),
658 silc_packet_get_context(cmd->sock),
661 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
665 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
666 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
667 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
669 SILC_LOG_DEBUG(("stat.clients %d->%d", server->stat.clients,
670 server->stat.clients + 1));
671 server->stat.clients++;
673 /* We have the client already, update the data */
675 SILC_LOG_DEBUG(("Updating client data"));
679 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
682 name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
685 SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY "
690 silc_free(client->nickname);
691 client->nickname = strdup(nick);
693 /* Update the context */
694 silc_idcache_update_by_context(global ? server->global_list->clients :
695 server->local_list->clients, client,
700 silc_free(client->username);
701 client->username = strdup(info);
704 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
705 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
714 if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
717 SILC_LOG_DEBUG(("Received server information"));
719 server_entry = silc_idlist_find_server_by_id(server->local_list,
720 &server_id, FALSE, NULL);
722 server_entry = silc_idlist_find_server_by_id(server->global_list,
723 &server_id, FALSE, NULL);
725 /* If router did not find such Server ID in its lists then this must
726 be bogus server or some router in the net is buggy. */
727 if (server->server_type != SILC_SERVER)
730 /* We don't have that server anywhere, add it. */
731 server_entry = silc_idlist_add_server(server->global_list,
733 silc_id_dup(&server_id,
736 SILC_PRIMARY_ROUTE(server));
740 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
741 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
742 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
747 case SILC_ID_CHANNEL:
751 if (!silc_id_payload_get_id(idp, &channel_id, sizeof(channel_id)))
754 SILC_LOG_DEBUG(("Received channel information"));
756 /* Check channel name */
757 info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
762 channel = silc_idlist_find_channel_by_name(server->local_list,
765 channel = silc_idlist_find_channel_by_name(server->global_list,
768 /* If router did not find such Channel ID in its lists then this must
769 be bogus channel or some router in the net is buggy. */
770 if (server->server_type != SILC_SERVER) {
775 /* We don't have that channel anywhere, add it. */
776 channel = silc_idlist_add_channel(server->global_list, strdup(name),
777 SILC_CHANNEL_MODE_NONE,
778 silc_id_dup(&channel_id,
780 server->router, NULL, NULL, 0);
791 silc_id_payload_free(idp);
795 silc_id_payload_free(idp);
799 /* Received reply for forwarded IDENTIFY command. We have received the
800 requested identify information now and we will cache it. After this we
801 will call the pending command so that the requestee gets the information
804 SILC_SERVER_CMD_REPLY_FUNC(identify)
806 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
807 SilcStatus status, error;
809 COMMAND_CHECK_STATUS;
811 if (!silc_server_command_reply_identify_save(cmd))
814 /* Pending callbacks are not executed if this was an list entry */
815 if (status != SILC_STATUS_OK &&
816 status != SILC_STATUS_LIST_END) {
817 silc_server_command_reply_free(cmd);
822 silc_server_command_process_error(cmd, error);
823 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
824 silc_server_command_reply_free(cmd);
828 silc_server_command_process_error(cmd, error);
829 silc_server_command_reply_free(cmd);
832 /* Received reply fro INFO command. Cache the server and its information */
834 SILC_SERVER_CMD_REPLY_FUNC(info)
836 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
837 SilcServer server = cmd->server;
838 SilcStatus status, error;
839 SilcServerEntry entry;
842 unsigned char *tmp, *name;
844 COMMAND_CHECK_STATUS;
847 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
851 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
855 entry = silc_idlist_find_server_by_id(server->local_list,
859 entry = silc_idlist_find_server_by_id(server->global_list,
863 /* Add the server to global list */
864 entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
865 silc_id_dup(SILC_ID_GET_ID(id),
867 silc_packet_get_context(cmd->sock),
872 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
876 /* Get the info string */
877 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
881 entry->server_info = tmp ? strdup(tmp) : NULL;
884 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
886 silc_server_command_reply_free(cmd);
889 /* Received reply fro MOTD command. */
891 SILC_SERVER_CMD_REPLY_FUNC(motd)
893 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
894 SilcServer server = cmd->server;
895 SilcStatus status, error;
896 SilcServerEntry entry = NULL;
901 COMMAND_CHECK_STATUS;
904 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
907 entry = silc_idlist_find_server_by_id(server->local_list,
911 entry = silc_idlist_find_server_by_id(server->global_list,
917 /* If router did not find such Server ID in its lists then this must
918 be bogus client or some router in the net is buggy. */
919 if (server->server_type != SILC_SERVER)
923 cmd->server->stat.commands_sent++;
925 /* entry isn't known so we IDENTIFY it. otherwise the
926 silc_server_command_motd won't know about it and tell
927 the client that there is no such server */
928 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
929 buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
930 ++server->cmd_ident, 5,
931 1, NULL, 0, 2, NULL, 0,
932 3, NULL, 0, 4, NULL, 0,
934 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
935 SILC_PACKET_COMMAND, 0, buffer->data,
936 silc_buffer_len(buffer));
937 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
939 silc_server_command_reply_motd,
941 silc_buffer_free(buffer);
947 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
954 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
956 silc_server_command_reply_free(cmd);
962 /* Received reply for forwarded JOIN command. Router has created or joined
963 the client to the channel. We save some channel information locally
966 SILC_SERVER_CMD_REPLY_FUNC(join)
968 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
969 SilcServer server = cmd->server;
970 SilcIDCacheEntry cache = NULL;
971 SilcStatus status, error;
973 SilcChannelEntry entry;
974 SilcHmac hmac = NULL;
975 SilcUInt32 len, list_count;
976 char *channel_name, *channel_namec = NULL, *tmp;
977 SilcUInt32 mode, created;
978 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
979 SilcPublicKey founder_key = NULL;
981 COMMAND_CHECK_STATUS;
983 /* Get channel name */
984 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
989 if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id, NULL))
993 if (!silc_argument_get_decoded(cmd->args, 4, SILC_ARGUMENT_ID, &id2, NULL))
997 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1000 SILC_GET32_MSB(mode, tmp);
1002 /* Get created boolean value */
1003 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1006 SILC_GET32_MSB(created, tmp);
1007 if (created != 0 && created != 1)
1010 /* Get channel key */
1011 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
1013 keyp = silc_buffer_alloc(len);
1014 silc_buffer_pull_tail(keyp, silc_buffer_truelen(keyp));
1015 silc_buffer_put(keyp, tmp, len);
1019 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1021 if (!silc_hmac_alloc(tmp, NULL, &hmac))
1025 /* Get the list count */
1026 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1029 SILC_GET32_MSB(list_count, tmp);
1031 /* Get Client ID list */
1032 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1036 client_id_list = silc_buffer_alloc(len);
1037 silc_buffer_pull_tail(client_id_list, len);
1038 silc_buffer_put(client_id_list, tmp, len);
1040 /* Get client mode list */
1041 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1045 client_mode_list = silc_buffer_alloc(len);
1046 silc_buffer_pull_tail(client_mode_list, len);
1047 silc_buffer_put(client_mode_list, tmp, len);
1049 /* Get founder key */
1050 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1052 silc_public_key_payload_decode(tmp, len, &founder_key);
1054 /* See whether we already have the channel. */
1055 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
1056 SILC_STRING_UTF8, 256, NULL);
1059 entry = silc_idlist_find_channel_by_name(server->local_list,
1060 channel_namec, &cache);
1062 /* Add new channel */
1064 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1065 (created == 0 ? "existing" : "created"), channel_name,
1066 silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL)));
1068 /* If the channel is found from global list we must move it to the
1070 entry = silc_idlist_find_channel_by_name(server->global_list,
1071 channel_namec, &cache);
1073 silc_idlist_del_channel(server->global_list, entry);
1075 /* Add the channel to our local list. */
1076 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1077 SILC_CHANNEL_MODE_NONE,
1078 silc_id_dup(SILC_ID_GET_ID(id),
1080 server->router, NULL, NULL, hmac);
1085 server->stat.my_channels++;
1086 server->stat.channels++;
1088 /* The entry exists. */
1090 /* If ID has changed, then update it to the cache too. */
1091 if (!SILC_ID_CHANNEL_COMPARE(entry->id, SILC_ID_GET_ID(id)))
1092 silc_idlist_replace_channel_id(server->local_list, entry->id,
1093 SILC_ID_GET_ID(id));
1095 entry->disabled = FALSE;
1097 /* Remove the founder auth data if the mode is not set but we have
1098 them in the entry */
1099 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1100 silc_pkcs_public_key_free(entry->founder_key);
1101 entry->founder_key = NULL;
1106 if (entry->founder_key)
1107 silc_pkcs_public_key_free(entry->founder_key);
1108 entry->founder_key = founder_key;
1112 if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1113 silc_free(entry->hmac_name);
1114 entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1117 /* Get the ban list */
1118 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1119 if (tmp && len > 2) {
1120 SilcArgumentPayload iargs;
1122 SILC_GET16_MSB(iargc, tmp);
1123 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1125 /* Delete old ban list */
1126 if (entry->ban_list)
1127 silc_hash_table_free(entry->ban_list);
1129 silc_hash_table_alloc(0, silc_hash_ptr,
1131 silc_server_inviteban_destruct, entry, TRUE);
1133 /* Add new ban list */
1134 silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1135 silc_argument_payload_free(iargs);
1139 /* Get the invite list */
1140 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1141 if (tmp && len > 2) {
1142 SilcArgumentPayload iargs;
1144 SILC_GET16_MSB(iargc, tmp);
1145 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1147 /* Delete old invite list */
1148 if (entry->invite_list)
1149 silc_hash_table_free(entry->invite_list);
1150 entry->invite_list =
1151 silc_hash_table_alloc(0, silc_hash_ptr,
1153 silc_server_inviteban_destruct, entry, TRUE);
1155 /* Add new invite list */
1156 silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1157 silc_argument_payload_free(iargs);
1162 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1164 silc_free(entry->topic);
1165 entry->topic = strdup(tmp);
1168 /* Get channel public key list */
1169 tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1170 if (tmp && server->server_type != SILC_ROUTER)
1171 silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1173 /* The the user limit */
1174 tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1175 if (tmp && len == 4)
1176 SILC_GET32_MSB(entry->user_limit, tmp);
1178 /* If channel was not created we know there is global users on the
1180 entry->global_users = (created == 0 ? TRUE : FALSE);
1182 /* If channel was just created the mask must be zero */
1183 if (!entry->global_users && mode)
1186 /* Save channel mode */
1189 /* Save channel key */
1191 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1192 silc_server_save_channel_key(server, keyp, entry);
1193 silc_buffer_free(keyp);
1196 /* Save the users to the channel */
1197 silc_server_save_users_on_channel(server, cmd->sock, entry,
1198 SILC_ID_GET_ID(id2), client_id_list,
1199 client_mode_list, list_count);
1200 entry->users_resolved = TRUE;
1203 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1205 silc_free(channel_namec);
1207 silc_hmac_free(hmac);
1208 silc_server_command_reply_free(cmd);
1211 silc_pkcs_public_key_free(founder_key);
1213 silc_buffer_free(client_id_list);
1214 if (client_mode_list)
1215 silc_buffer_free(client_mode_list);
1218 /* Received reply to STATS command. */
1220 SILC_SERVER_CMD_REPLY_FUNC(stats)
1222 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1223 SilcServer server = cmd->server;
1224 SilcStatus status, error;
1227 SilcBufferStruct buf;
1229 COMMAND_CHECK_STATUS;
1231 /* Get statistics structure */
1232 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1233 if (server->server_type != SILC_ROUTER && tmp) {
1234 silc_buffer_set(&buf, tmp, tmp_len);
1235 silc_buffer_unformat(&buf,
1236 SILC_STR_UI_INT(NULL),
1237 SILC_STR_UI_INT(NULL),
1238 SILC_STR_UI_INT(NULL),
1239 SILC_STR_UI_INT(NULL),
1240 SILC_STR_UI_INT(NULL),
1241 SILC_STR_UI_INT(NULL),
1242 SILC_STR_UI_INT(&server->stat.cell_clients),
1243 SILC_STR_UI_INT(&server->stat.cell_channels),
1244 SILC_STR_UI_INT(&server->stat.cell_servers),
1245 SILC_STR_UI_INT(&server->stat.clients),
1246 SILC_STR_UI_INT(&server->stat.channels),
1247 SILC_STR_UI_INT(&server->stat.servers),
1248 SILC_STR_UI_INT(&server->stat.routers),
1249 SILC_STR_UI_INT(&server->stat.server_ops),
1250 SILC_STR_UI_INT(&server->stat.router_ops),
1254 SILC_LOG_DEBUG(("stat.clients = %d", server->stat.clients));
1257 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1259 silc_server_command_reply_free(cmd);
1262 SILC_SERVER_CMD_REPLY_FUNC(users)
1264 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1265 SilcServer server = cmd->server;
1266 SilcStatus status, error;
1267 SilcChannelEntry channel;
1269 SilcBuffer client_id_list;
1270 SilcBuffer client_mode_list;
1273 SilcUInt32 list_count;
1275 COMMAND_CHECK_STATUS;
1277 /* Get channel ID */
1278 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1281 /* Get channel entry */
1282 channel = silc_idlist_find_channel_by_id(server->local_list,
1283 SILC_ID_GET_ID(id), NULL);
1285 channel = silc_idlist_find_channel_by_id(server->global_list,
1286 SILC_ID_GET_ID(id), NULL);
1290 if (cmd->pending || server->server_type != SILC_SERVER)
1293 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1294 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1295 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1296 1, 5, idp->data, silc_buffer_len(idp));
1297 silc_buffer_free(idp);
1299 /* Register pending command callback. After we've received the channel
1300 information we will reprocess this command reply by re-calling this
1301 USERS command reply callback. */
1302 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1304 silc_server_command_reply_users, cmd);
1306 cmd->pending = TRUE;
1311 /* Get the list count */
1312 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1315 SILC_GET32_MSB(list_count, tmp);
1317 /* Get Client ID list */
1318 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1322 client_id_list = silc_buffer_alloc(tmp_len);
1323 silc_buffer_pull_tail(client_id_list, tmp_len);
1324 silc_buffer_put(client_id_list, tmp, tmp_len);
1326 /* Get client mode list */
1327 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1331 client_mode_list = silc_buffer_alloc(tmp_len);
1332 silc_buffer_pull_tail(client_mode_list, tmp_len);
1333 silc_buffer_put(client_mode_list, tmp, tmp_len);
1335 /* Save the users to the channel */
1336 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1337 client_id_list, client_mode_list,
1340 channel->global_users = silc_server_channel_has_global(channel);
1341 channel->users_resolved = TRUE;
1343 silc_buffer_free(client_id_list);
1344 silc_buffer_free(client_mode_list);
1347 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1349 silc_server_command_reply_free(cmd);
1352 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1354 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1355 SilcServer server = cmd->server;
1356 SilcStatus status, error;
1357 SilcClientEntry client = NULL;
1358 SilcServerEntry server_entry = NULL;
1359 SilcClientID client_id;
1360 SilcServerID server_id;
1363 SilcIDPayload idp = NULL;
1365 SilcPublicKey public_key = NULL;
1367 COMMAND_CHECK_STATUS;
1369 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1372 idp = silc_id_payload_parse(tmp, len);
1376 /* Get the public key payload */
1377 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1381 /* Decode the public key payload */
1382 if (!silc_public_key_payload_decode(tmp, len, &public_key))
1385 id_type = silc_id_payload_get_type(idp);
1386 if (id_type == SILC_ID_CLIENT) {
1387 silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
1389 client = silc_idlist_find_client_by_id(server->local_list, &client_id,
1392 client = silc_idlist_find_client_by_id(server->global_list,
1393 &client_id, TRUE, NULL);
1398 if (!client->data.public_key) {
1399 /* Add client's public key to repository */
1400 if (!silc_server_get_public_key_by_client(server, client, NULL))
1401 silc_skr_add_public_key_simple(server->repository,
1403 SILC_SKR_USAGE_IDENTIFICATION,
1405 client->data.public_key = public_key;
1408 } else if (id_type == SILC_ID_SERVER) {
1409 silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
1411 server_entry = silc_idlist_find_server_by_id(server->local_list,
1412 &server_id, TRUE, NULL);
1413 if (!server_entry) {
1414 server_entry = silc_idlist_find_server_by_id(server->global_list,
1415 &server_id, TRUE, NULL);
1420 server_entry->data.public_key = public_key;
1427 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1429 silc_id_payload_free(idp);
1431 silc_pkcs_public_key_free(public_key);
1433 silc_server_command_reply_free(cmd);
1436 SILC_SERVER_CMD_REPLY_FUNC(list)
1438 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1439 SilcServer server = cmd->server;
1440 SilcStatus status, error;
1442 SilcChannelEntry channel;
1443 SilcIDCacheEntry cache;
1444 unsigned char *tmp, *name, *namec = NULL, *topic;
1445 SilcUInt32 usercount = 0;
1446 SilcBool global_list = FALSE;
1448 COMMAND_CHECK_STATUS;
1450 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1453 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1454 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1455 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1457 SILC_GET32_MSB(usercount, tmp);
1459 namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
1464 /* Add the channel entry if we do not have it already */
1465 channel = silc_idlist_find_channel_by_name(server->local_list,
1468 channel = silc_idlist_find_channel_by_name(server->global_list,
1473 /* If router did not find such channel in its lists then this must
1474 be bogus channel or some router in the net is buggy. */
1475 if (server->server_type != SILC_SERVER)
1478 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1479 SILC_CHANNEL_MODE_NONE,
1480 silc_id_dup(SILC_ID_GET_ID(id),
1482 server->router, NULL, NULL, NULL);
1487 channel->user_count = usercount;
1490 silc_free(channel->topic);
1491 channel->topic = strdup(topic);
1494 /* Pending callbacks are not executed if this was an list entry */
1495 if (status != SILC_STATUS_OK &&
1496 status != SILC_STATUS_LIST_END) {
1497 silc_server_command_reply_free(cmd);
1502 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1505 silc_server_command_reply_free(cmd);
1508 SILC_SERVER_CMD_REPLY_FUNC(watch)
1510 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1511 SilcStatus status, error;
1513 COMMAND_CHECK_STATUS;
1516 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1518 silc_server_command_reply_free(cmd);
1521 SILC_SERVER_CMD_REPLY_FUNC(ping)
1523 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1524 SilcStatus status, error;
1526 COMMAND_CHECK_STATUS;
1529 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1531 silc_server_command_reply_free(cmd);