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 nick, hostname ? hostname : ""));
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 /* Update cache entry */
538 silc_idcache_update_by_context(global ? server->global_list->clients :
539 server->local_list->clients, client, NULL,
543 /* If client is global and is not on any channel then add that we'll
544 expire the entry after a while. */
546 silc_idlist_find_client_by_id(server->global_list, client->id,
548 if (!silc_hash_table_count(client->channels))
549 silc_dlist_add(server->expired_clients, client);
555 /* Received reply for WHOWAS command. Cache the client information only for
556 a short period of time. */
558 SILC_SERVER_CMD_REPLY_FUNC(whowas)
560 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
561 SilcStatus status, error;
563 COMMAND_CHECK_STATUS;
565 if (!silc_server_command_reply_whowas_save(cmd))
568 /* Pending callbacks are not executed if this was an list entry */
569 if (status != SILC_STATUS_OK &&
570 status != SILC_STATUS_LIST_END) {
571 silc_server_command_reply_free(cmd);
576 silc_server_command_process_error(cmd, error);
577 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
578 silc_server_command_reply_free(cmd);
582 silc_server_command_process_error(cmd, error);
583 silc_server_command_reply_free(cmd);
586 /* Caches the received IDENTIFY information. */
589 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
591 SilcServer server = cmd->server;
592 SilcUInt32 len, id_len;
593 unsigned char *id_data;
595 SilcClientID client_id;
596 SilcServerID server_id;
597 SilcChannelID*channel_id;
598 SilcClientEntry client;
599 SilcServerEntry server_entry;
600 SilcChannelEntry channel;
603 SilcIDPayload idp = NULL;
606 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
609 idp = silc_id_payload_parse(id_data, id_len);
613 name = silc_argument_get_arg_type(cmd->args, 3, &len);
614 info = silc_argument_get_arg_type(cmd->args, 4, &len);
616 id_type = silc_id_payload_get_type(idp);
620 if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
623 SILC_LOG_DEBUG(("Received client information"));
625 client = silc_idlist_find_client_by_id(server->local_list,
626 &client_id, FALSE, NULL);
628 client = silc_idlist_find_client_by_id(server->global_list, &client_id,
633 /* If router did not find such Client ID in its lists then this must
634 be bogus client or some router in the net is buggy. */
635 if (server->server_type != SILC_SERVER)
640 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
642 /* We don't have that client anywhere, add it. The client is added
643 to global list since server didn't have it in the lists so it must be
645 client = silc_idlist_add_client(server->global_list,
646 nick[0] ? nick : NULL, info, NULL,
647 silc_id_dup(&client_id, SILC_ID_CLIENT),
648 silc_packet_get_context(cmd->sock),
651 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
655 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
656 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
657 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
659 /* We have the client already, update the data */
661 SILC_LOG_DEBUG(("Updating client data"));
665 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
668 name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
671 SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY "
676 silc_free(client->nickname);
677 client->nickname = strdup(nick);
679 /* Update the context */
680 silc_idcache_update_by_context(global ? server->global_list->clients :
681 server->local_list->clients, client,
686 silc_free(client->username);
687 client->username = strdup(info);
690 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
691 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
700 if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
703 SILC_LOG_DEBUG(("Received server information"));
705 server_entry = silc_idlist_find_server_by_id(server->local_list,
706 &server_id, FALSE, NULL);
708 server_entry = silc_idlist_find_server_by_id(server->global_list,
709 &server_id, FALSE, NULL);
711 /* If router did not find such Server ID in its lists then this must
712 be bogus server or some router in the net is buggy. */
713 if (server->server_type != SILC_SERVER)
716 /* We don't have that server anywhere, add it. */
717 server_entry = silc_idlist_add_server(server->global_list,
719 silc_id_dup(&server_id,
722 SILC_PRIMARY_ROUTE(server));
726 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
727 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
728 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
733 case SILC_ID_CHANNEL:
737 if (!silc_id_payload_get_id(idp, &channel_id, sizeof(channel_id)))
740 SILC_LOG_DEBUG(("Received channel information"));
742 /* Check channel name */
743 info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
748 channel = silc_idlist_find_channel_by_name(server->local_list,
751 channel = silc_idlist_find_channel_by_name(server->global_list,
754 /* If router did not find such Channel ID in its lists then this must
755 be bogus channel or some router in the net is buggy. */
756 if (server->server_type != SILC_SERVER) {
761 /* We don't have that channel anywhere, add it. */
762 channel = silc_idlist_add_channel(server->global_list, strdup(name),
763 SILC_CHANNEL_MODE_NONE,
764 silc_id_dup(&channel_id,
766 server->router, NULL, NULL, 0);
777 silc_id_payload_free(idp);
781 silc_id_payload_free(idp);
785 /* Received reply for forwarded IDENTIFY command. We have received the
786 requested identify information now and we will cache it. After this we
787 will call the pending command so that the requestee gets the information
790 SILC_SERVER_CMD_REPLY_FUNC(identify)
792 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
793 SilcStatus status, error;
795 COMMAND_CHECK_STATUS;
797 if (!silc_server_command_reply_identify_save(cmd))
800 /* Pending callbacks are not executed if this was an list entry */
801 if (status != SILC_STATUS_OK &&
802 status != SILC_STATUS_LIST_END) {
803 silc_server_command_reply_free(cmd);
808 silc_server_command_process_error(cmd, error);
809 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
810 silc_server_command_reply_free(cmd);
814 silc_server_command_process_error(cmd, error);
815 silc_server_command_reply_free(cmd);
818 /* Received reply fro INFO command. Cache the server and its information */
820 SILC_SERVER_CMD_REPLY_FUNC(info)
822 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
823 SilcServer server = cmd->server;
824 SilcStatus status, error;
825 SilcServerEntry entry;
828 unsigned char *tmp, *name;
830 COMMAND_CHECK_STATUS;
833 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
837 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
841 entry = silc_idlist_find_server_by_id(server->local_list,
845 entry = silc_idlist_find_server_by_id(server->global_list,
849 /* Add the server to global list */
850 entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
851 silc_id_dup(SILC_ID_GET_ID(id),
853 silc_packet_get_context(cmd->sock),
858 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
862 /* Get the info string */
863 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
867 entry->server_info = tmp ? strdup(tmp) : NULL;
870 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
872 silc_server_command_reply_free(cmd);
875 /* Received reply fro MOTD command. */
877 SILC_SERVER_CMD_REPLY_FUNC(motd)
879 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
880 SilcServer server = cmd->server;
881 SilcStatus status, error;
882 SilcServerEntry entry = NULL;
887 COMMAND_CHECK_STATUS;
890 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
893 entry = silc_idlist_find_server_by_id(server->local_list,
897 entry = silc_idlist_find_server_by_id(server->global_list,
903 /* If router did not find such Server ID in its lists then this must
904 be bogus client or some router in the net is buggy. */
905 if (server->server_type != SILC_SERVER)
909 cmd->server->stat.commands_sent++;
911 /* entry isn't known so we IDENTIFY it. otherwise the
912 silc_server_command_motd won't know about it and tell
913 the client that there is no such server */
914 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
915 buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
916 ++server->cmd_ident, 5,
917 1, NULL, 0, 2, NULL, 0,
918 3, NULL, 0, 4, NULL, 0,
920 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
921 SILC_PACKET_COMMAND, 0, buffer->data,
922 silc_buffer_len(buffer));
923 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
925 silc_server_command_reply_motd,
927 silc_buffer_free(buffer);
933 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
940 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
942 silc_server_command_reply_free(cmd);
948 /* Received reply for forwarded JOIN command. Router has created or joined
949 the client to the channel. We save some channel information locally
952 SILC_SERVER_CMD_REPLY_FUNC(join)
954 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
955 SilcServer server = cmd->server;
956 SilcIDCacheEntry cache = NULL;
957 SilcStatus status, error;
959 SilcChannelEntry entry;
960 SilcHmac hmac = NULL;
961 SilcUInt32 len, list_count;
962 char *channel_name, *channel_namec = NULL, *tmp;
963 SilcUInt32 mode, created;
964 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
965 SilcPublicKey founder_key = NULL;
967 COMMAND_CHECK_STATUS;
969 /* Get channel name */
970 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
975 if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id, NULL))
979 if (!silc_argument_get_decoded(cmd->args, 4, SILC_ARGUMENT_ID, &id2, NULL))
983 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
986 SILC_GET32_MSB(mode, tmp);
988 /* Get created boolean value */
989 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
992 SILC_GET32_MSB(created, tmp);
993 if (created != 0 && created != 1)
996 /* Get channel key */
997 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
999 keyp = silc_buffer_alloc(len);
1000 silc_buffer_pull_tail(keyp, silc_buffer_truelen(keyp));
1001 silc_buffer_put(keyp, tmp, len);
1005 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1007 if (!silc_hmac_alloc(tmp, NULL, &hmac))
1011 /* Get the list count */
1012 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1015 SILC_GET32_MSB(list_count, tmp);
1017 /* Get Client ID list */
1018 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1022 client_id_list = silc_buffer_alloc(len);
1023 silc_buffer_pull_tail(client_id_list, len);
1024 silc_buffer_put(client_id_list, tmp, len);
1026 /* Get client mode list */
1027 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1031 client_mode_list = silc_buffer_alloc(len);
1032 silc_buffer_pull_tail(client_mode_list, len);
1033 silc_buffer_put(client_mode_list, tmp, len);
1035 /* Get founder key */
1036 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1038 silc_public_key_payload_decode(tmp, len, &founder_key);
1040 /* See whether we already have the channel. */
1041 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
1042 SILC_STRING_UTF8, 256, NULL);
1045 entry = silc_idlist_find_channel_by_name(server->local_list,
1046 channel_namec, &cache);
1048 /* Add new channel */
1050 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1051 (created == 0 ? "existing" : "created"), channel_name,
1052 silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL)));
1054 /* If the channel is found from global list we must move it to the
1056 entry = silc_idlist_find_channel_by_name(server->global_list,
1057 channel_namec, &cache);
1059 silc_idlist_del_channel(server->global_list, entry);
1061 /* Add the channel to our local list. */
1062 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1063 SILC_CHANNEL_MODE_NONE,
1064 silc_id_dup(SILC_ID_GET_ID(id),
1066 server->router, NULL, NULL, hmac);
1071 server->stat.my_channels++;
1072 server->stat.channels++;
1074 /* The entry exists. */
1076 /* If ID has changed, then update it to the cache too. */
1077 if (!SILC_ID_CHANNEL_COMPARE(entry->id, SILC_ID_GET_ID(id)))
1078 silc_idlist_replace_channel_id(server->local_list, entry->id,
1079 SILC_ID_GET_ID(id));
1081 entry->disabled = FALSE;
1083 /* Remove the founder auth data if the mode is not set but we have
1084 them in the entry */
1085 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1086 silc_pkcs_public_key_free(entry->founder_key);
1087 entry->founder_key = NULL;
1092 if (entry->founder_key)
1093 silc_pkcs_public_key_free(entry->founder_key);
1094 entry->founder_key = founder_key;
1098 if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1099 silc_free(entry->hmac_name);
1100 entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1103 /* Get the ban list */
1104 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1105 if (tmp && len > 2) {
1106 SilcArgumentPayload iargs;
1108 SILC_GET16_MSB(iargc, tmp);
1109 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1111 /* Delete old ban list */
1112 if (entry->ban_list)
1113 silc_hash_table_free(entry->ban_list);
1115 silc_hash_table_alloc(0, silc_hash_ptr,
1117 silc_server_inviteban_destruct, entry, TRUE);
1119 /* Add new ban list */
1120 silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1121 silc_argument_payload_free(iargs);
1125 /* Get the invite list */
1126 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1127 if (tmp && len > 2) {
1128 SilcArgumentPayload iargs;
1130 SILC_GET16_MSB(iargc, tmp);
1131 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1133 /* Delete old invite list */
1134 if (entry->invite_list)
1135 silc_hash_table_free(entry->invite_list);
1136 entry->invite_list =
1137 silc_hash_table_alloc(0, silc_hash_ptr,
1139 silc_server_inviteban_destruct, entry, TRUE);
1141 /* Add new invite list */
1142 silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1143 silc_argument_payload_free(iargs);
1148 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1150 silc_free(entry->topic);
1151 entry->topic = strdup(tmp);
1154 /* Get channel public key list */
1155 tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1156 if (tmp && server->server_type != SILC_ROUTER)
1157 silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1159 /* The the user limit */
1160 tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1161 if (tmp && len == 4)
1162 SILC_GET32_MSB(entry->user_limit, tmp);
1164 /* If channel was not created we know there is global users on the
1166 entry->global_users = (created == 0 ? TRUE : FALSE);
1168 /* If channel was just created the mask must be zero */
1169 if (!entry->global_users && mode)
1172 /* Save channel mode */
1175 /* Save channel key */
1177 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1178 silc_server_save_channel_key(server, keyp, entry);
1179 silc_buffer_free(keyp);
1182 /* Save the users to the channel */
1183 silc_server_save_users_on_channel(server, cmd->sock, entry,
1184 SILC_ID_GET_ID(id2), client_id_list,
1185 client_mode_list, list_count);
1186 entry->users_resolved = TRUE;
1189 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1191 silc_free(channel_namec);
1193 silc_hmac_free(hmac);
1194 silc_server_command_reply_free(cmd);
1197 silc_pkcs_public_key_free(founder_key);
1199 silc_buffer_free(client_id_list);
1200 if (client_mode_list)
1201 silc_buffer_free(client_mode_list);
1204 /* Received reply to STATS command. */
1206 SILC_SERVER_CMD_REPLY_FUNC(stats)
1208 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1209 SilcServer server = cmd->server;
1210 SilcStatus status, error;
1213 SilcBufferStruct buf;
1215 COMMAND_CHECK_STATUS;
1217 /* Get statistics structure */
1218 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1219 if (server->server_type != SILC_ROUTER && tmp) {
1220 silc_buffer_set(&buf, tmp, tmp_len);
1221 silc_buffer_unformat(&buf,
1222 SILC_STR_UI_INT(NULL),
1223 SILC_STR_UI_INT(NULL),
1224 SILC_STR_UI_INT(NULL),
1225 SILC_STR_UI_INT(NULL),
1226 SILC_STR_UI_INT(NULL),
1227 SILC_STR_UI_INT(NULL),
1228 SILC_STR_UI_INT(&server->stat.cell_clients),
1229 SILC_STR_UI_INT(&server->stat.cell_channels),
1230 SILC_STR_UI_INT(&server->stat.cell_servers),
1231 SILC_STR_UI_INT(&server->stat.clients),
1232 SILC_STR_UI_INT(&server->stat.channels),
1233 SILC_STR_UI_INT(&server->stat.servers),
1234 SILC_STR_UI_INT(&server->stat.routers),
1235 SILC_STR_UI_INT(&server->stat.server_ops),
1236 SILC_STR_UI_INT(&server->stat.router_ops),
1241 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1243 silc_server_command_reply_free(cmd);
1246 SILC_SERVER_CMD_REPLY_FUNC(users)
1248 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1249 SilcServer server = cmd->server;
1250 SilcStatus status, error;
1251 SilcChannelEntry channel;
1253 SilcBuffer client_id_list;
1254 SilcBuffer client_mode_list;
1257 SilcUInt32 list_count;
1259 COMMAND_CHECK_STATUS;
1261 /* Get channel ID */
1262 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1265 /* Get channel entry */
1266 channel = silc_idlist_find_channel_by_id(server->local_list,
1267 SILC_ID_GET_ID(id), NULL);
1269 channel = silc_idlist_find_channel_by_id(server->global_list,
1270 SILC_ID_GET_ID(id), NULL);
1274 if (server->server_type != SILC_SERVER)
1277 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1278 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1279 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1280 1, 5, idp->data, silc_buffer_len(idp));
1281 silc_buffer_free(idp);
1283 /* Register pending command callback. After we've received the channel
1284 information we will reprocess this command reply by re-calling this
1285 USERS command reply callback. */
1286 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1288 silc_server_command_reply_users, cmd);
1293 /* Get the list count */
1294 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1297 SILC_GET32_MSB(list_count, tmp);
1299 /* Get Client ID list */
1300 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1304 client_id_list = silc_buffer_alloc(tmp_len);
1305 silc_buffer_pull_tail(client_id_list, tmp_len);
1306 silc_buffer_put(client_id_list, tmp, tmp_len);
1308 /* Get client mode list */
1309 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1313 client_mode_list = silc_buffer_alloc(tmp_len);
1314 silc_buffer_pull_tail(client_mode_list, tmp_len);
1315 silc_buffer_put(client_mode_list, tmp, tmp_len);
1317 /* Save the users to the channel */
1318 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1319 client_id_list, client_mode_list,
1322 channel->global_users = silc_server_channel_has_global(channel);
1323 channel->users_resolved = TRUE;
1325 silc_buffer_free(client_id_list);
1326 silc_buffer_free(client_mode_list);
1329 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1331 silc_server_command_reply_free(cmd);
1334 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1336 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1337 SilcServer server = cmd->server;
1338 SilcStatus status, error;
1339 SilcClientEntry client = NULL;
1340 SilcServerEntry server_entry = NULL;
1341 SilcClientID client_id;
1342 SilcServerID server_id;
1345 SilcIDPayload idp = NULL;
1347 SilcPublicKey public_key = NULL;
1349 COMMAND_CHECK_STATUS;
1351 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1354 idp = silc_id_payload_parse(tmp, len);
1358 /* Get the public key payload */
1359 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1363 /* Decode the public key payload */
1364 if (!silc_public_key_payload_decode(tmp, len, &public_key))
1367 id_type = silc_id_payload_get_type(idp);
1368 if (id_type == SILC_ID_CLIENT) {
1369 silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
1371 client = silc_idlist_find_client_by_id(server->local_list, &client_id,
1374 client = silc_idlist_find_client_by_id(server->global_list,
1375 &client_id, TRUE, NULL);
1380 if (!client->data.public_key) {
1381 /* Add client's public key to repository */
1382 if (!silc_server_get_public_key_by_client(server, client, NULL))
1383 silc_skr_add_public_key_simple(server->repository,
1385 SILC_SKR_USAGE_IDENTIFICATION,
1387 client->data.public_key = public_key;
1390 } else if (id_type == SILC_ID_SERVER) {
1391 silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
1393 server_entry = silc_idlist_find_server_by_id(server->local_list,
1394 &server_id, TRUE, NULL);
1395 if (!server_entry) {
1396 server_entry = silc_idlist_find_server_by_id(server->global_list,
1397 &server_id, TRUE, NULL);
1402 server_entry->data.public_key = public_key;
1409 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1411 silc_id_payload_free(idp);
1413 silc_pkcs_public_key_free(public_key);
1415 silc_server_command_reply_free(cmd);
1418 SILC_SERVER_CMD_REPLY_FUNC(list)
1420 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1421 SilcServer server = cmd->server;
1422 SilcStatus status, error;
1424 SilcChannelEntry channel;
1425 SilcIDCacheEntry cache;
1426 unsigned char *tmp, *name, *namec = NULL, *topic;
1427 SilcUInt32 usercount = 0;
1428 SilcBool global_list = FALSE;
1430 COMMAND_CHECK_STATUS;
1432 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1435 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1436 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1437 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1439 SILC_GET32_MSB(usercount, tmp);
1441 namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
1446 /* Add the channel entry if we do not have it already */
1447 channel = silc_idlist_find_channel_by_name(server->local_list,
1450 channel = silc_idlist_find_channel_by_name(server->global_list,
1455 /* If router did not find such channel in its lists then this must
1456 be bogus channel or some router in the net is buggy. */
1457 if (server->server_type != SILC_SERVER)
1460 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1461 SILC_CHANNEL_MODE_NONE,
1462 silc_id_dup(SILC_ID_GET_ID(id),
1464 server->router, NULL, NULL, NULL);
1469 channel->user_count = usercount;
1472 silc_free(channel->topic);
1473 channel->topic = strdup(topic);
1476 /* Pending callbacks are not executed if this was an list entry */
1477 if (status != SILC_STATUS_OK &&
1478 status != SILC_STATUS_LIST_END) {
1479 silc_server_command_reply_free(cmd);
1484 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1487 silc_server_command_reply_free(cmd);
1490 SILC_SERVER_CMD_REPLY_FUNC(watch)
1492 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1493 SilcStatus status, error;
1495 COMMAND_CHECK_STATUS;
1498 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1500 silc_server_command_reply_free(cmd);
1503 SILC_SERVER_CMD_REPLY_FUNC(ping)
1505 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1506 SilcStatus status, error;
1508 COMMAND_CHECK_STATUS;
1511 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1513 silc_server_command_reply_free(cmd);