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;
536 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
538 /* Update cache entry */
539 silc_idcache_update_by_context(global ? server->global_list->clients :
540 server->local_list->clients, client, NULL,
544 /* If client is global and is not on any channel then add that we'll
545 expire the entry after a while. */
547 client = silc_idlist_find_client_by_id(server->global_list, client->id,
549 if (client && !silc_hash_table_count(client->channels)) {
550 silc_dlist_del(server->expired_clients, client);
551 silc_dlist_add(server->expired_clients, client);
558 /* Received reply for WHOWAS command. Cache the client information only for
559 a short period of time. */
561 SILC_SERVER_CMD_REPLY_FUNC(whowas)
563 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
564 SilcStatus status, error;
566 COMMAND_CHECK_STATUS;
568 if (!silc_server_command_reply_whowas_save(cmd))
571 /* Pending callbacks are not executed if this was an list entry */
572 if (status != SILC_STATUS_OK &&
573 status != SILC_STATUS_LIST_END) {
574 silc_server_command_reply_free(cmd);
579 silc_server_command_process_error(cmd, error);
580 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
581 silc_server_command_reply_free(cmd);
585 silc_server_command_process_error(cmd, error);
586 silc_server_command_reply_free(cmd);
589 /* Caches the received IDENTIFY information. */
592 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
594 SilcServer server = cmd->server;
595 SilcUInt32 len, id_len;
596 unsigned char *id_data;
598 SilcClientID client_id;
599 SilcServerID server_id;
600 SilcChannelID*channel_id;
601 SilcClientEntry client;
602 SilcServerEntry server_entry;
603 SilcChannelEntry channel;
606 SilcIDPayload idp = NULL;
609 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
612 idp = silc_id_payload_parse(id_data, id_len);
616 name = silc_argument_get_arg_type(cmd->args, 3, &len);
617 info = silc_argument_get_arg_type(cmd->args, 4, &len);
619 id_type = silc_id_payload_get_type(idp);
623 if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
626 SILC_LOG_DEBUG(("Received client information"));
628 client = silc_idlist_find_client_by_id(server->local_list,
629 &client_id, FALSE, NULL);
631 client = silc_idlist_find_client_by_id(server->global_list, &client_id,
636 /* If router did not find such Client ID in its lists then this must
637 be bogus client or some router in the net is buggy. */
638 if (server->server_type != SILC_SERVER)
643 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
645 /* We don't have that client anywhere, add it. The client is added
646 to global list since server didn't have it in the lists so it must be
648 client = silc_idlist_add_client(server->global_list,
649 nick[0] ? nick : NULL, info, NULL,
650 silc_id_dup(&client_id, SILC_ID_CLIENT),
651 silc_packet_get_context(cmd->sock),
654 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
658 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
659 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
660 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
662 /* We have the client already, update the data */
664 SILC_LOG_DEBUG(("Updating client data"));
668 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
671 name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
674 SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY "
679 silc_free(client->nickname);
680 client->nickname = strdup(nick);
682 /* Update the context */
683 silc_idcache_update_by_context(global ? server->global_list->clients :
684 server->local_list->clients, client,
689 silc_free(client->username);
690 client->username = strdup(info);
693 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
694 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
703 if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
706 SILC_LOG_DEBUG(("Received server information"));
708 server_entry = silc_idlist_find_server_by_id(server->local_list,
709 &server_id, FALSE, NULL);
711 server_entry = silc_idlist_find_server_by_id(server->global_list,
712 &server_id, FALSE, NULL);
714 /* If router did not find such Server ID in its lists then this must
715 be bogus server or some router in the net is buggy. */
716 if (server->server_type != SILC_SERVER)
719 /* We don't have that server anywhere, add it. */
720 server_entry = silc_idlist_add_server(server->global_list,
722 silc_id_dup(&server_id,
725 SILC_PRIMARY_ROUTE(server));
729 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
730 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
731 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
736 case SILC_ID_CHANNEL:
740 if (!silc_id_payload_get_id(idp, &channel_id, sizeof(channel_id)))
743 SILC_LOG_DEBUG(("Received channel information"));
745 /* Check channel name */
746 info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
751 channel = silc_idlist_find_channel_by_name(server->local_list,
754 channel = silc_idlist_find_channel_by_name(server->global_list,
757 /* If router did not find such Channel ID in its lists then this must
758 be bogus channel or some router in the net is buggy. */
759 if (server->server_type != SILC_SERVER) {
764 /* We don't have that channel anywhere, add it. */
765 channel = silc_idlist_add_channel(server->global_list, strdup(name),
766 SILC_CHANNEL_MODE_NONE,
767 silc_id_dup(&channel_id,
769 server->router, NULL, NULL, 0);
780 silc_id_payload_free(idp);
784 silc_id_payload_free(idp);
788 /* Received reply for forwarded IDENTIFY command. We have received the
789 requested identify information now and we will cache it. After this we
790 will call the pending command so that the requestee gets the information
793 SILC_SERVER_CMD_REPLY_FUNC(identify)
795 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
796 SilcStatus status, error;
798 COMMAND_CHECK_STATUS;
800 if (!silc_server_command_reply_identify_save(cmd))
803 /* Pending callbacks are not executed if this was an list entry */
804 if (status != SILC_STATUS_OK &&
805 status != SILC_STATUS_LIST_END) {
806 silc_server_command_reply_free(cmd);
811 silc_server_command_process_error(cmd, error);
812 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
813 silc_server_command_reply_free(cmd);
817 silc_server_command_process_error(cmd, error);
818 silc_server_command_reply_free(cmd);
821 /* Received reply fro INFO command. Cache the server and its information */
823 SILC_SERVER_CMD_REPLY_FUNC(info)
825 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
826 SilcServer server = cmd->server;
827 SilcStatus status, error;
828 SilcServerEntry entry;
831 unsigned char *tmp, *name;
833 COMMAND_CHECK_STATUS;
836 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
840 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
844 entry = silc_idlist_find_server_by_id(server->local_list,
848 entry = silc_idlist_find_server_by_id(server->global_list,
852 /* Add the server to global list */
853 entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
854 silc_id_dup(SILC_ID_GET_ID(id),
856 silc_packet_get_context(cmd->sock),
861 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
865 /* Get the info string */
866 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
870 entry->server_info = tmp ? strdup(tmp) : NULL;
873 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
875 silc_server_command_reply_free(cmd);
878 /* Received reply fro MOTD command. */
880 SILC_SERVER_CMD_REPLY_FUNC(motd)
882 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
883 SilcServer server = cmd->server;
884 SilcStatus status, error;
885 SilcServerEntry entry = NULL;
890 COMMAND_CHECK_STATUS;
893 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
896 entry = silc_idlist_find_server_by_id(server->local_list,
900 entry = silc_idlist_find_server_by_id(server->global_list,
906 /* If router did not find such Server ID in its lists then this must
907 be bogus client or some router in the net is buggy. */
908 if (server->server_type != SILC_SERVER)
912 cmd->server->stat.commands_sent++;
914 /* entry isn't known so we IDENTIFY it. otherwise the
915 silc_server_command_motd won't know about it and tell
916 the client that there is no such server */
917 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
918 buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
919 ++server->cmd_ident, 5,
920 1, NULL, 0, 2, NULL, 0,
921 3, NULL, 0, 4, NULL, 0,
923 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
924 SILC_PACKET_COMMAND, 0, buffer->data,
925 silc_buffer_len(buffer));
926 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
928 silc_server_command_reply_motd,
930 silc_buffer_free(buffer);
936 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
943 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
945 silc_server_command_reply_free(cmd);
951 /* Received reply for forwarded JOIN command. Router has created or joined
952 the client to the channel. We save some channel information locally
955 SILC_SERVER_CMD_REPLY_FUNC(join)
957 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
958 SilcServer server = cmd->server;
959 SilcIDCacheEntry cache = NULL;
960 SilcStatus status, error;
962 SilcChannelEntry entry;
963 SilcHmac hmac = NULL;
964 SilcUInt32 len, list_count;
965 char *channel_name, *channel_namec = NULL, *tmp;
966 SilcUInt32 mode, created;
967 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
968 SilcPublicKey founder_key = NULL;
970 COMMAND_CHECK_STATUS;
972 /* Get channel name */
973 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
978 if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id, NULL))
982 if (!silc_argument_get_decoded(cmd->args, 4, SILC_ARGUMENT_ID, &id2, NULL))
986 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
989 SILC_GET32_MSB(mode, tmp);
991 /* Get created boolean value */
992 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
995 SILC_GET32_MSB(created, tmp);
996 if (created != 0 && created != 1)
999 /* Get channel key */
1000 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
1002 keyp = silc_buffer_alloc(len);
1003 silc_buffer_pull_tail(keyp, silc_buffer_truelen(keyp));
1004 silc_buffer_put(keyp, tmp, len);
1008 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1010 if (!silc_hmac_alloc(tmp, NULL, &hmac))
1014 /* Get the list count */
1015 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1018 SILC_GET32_MSB(list_count, tmp);
1020 /* Get Client ID list */
1021 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1025 client_id_list = silc_buffer_alloc(len);
1026 silc_buffer_pull_tail(client_id_list, len);
1027 silc_buffer_put(client_id_list, tmp, len);
1029 /* Get client mode list */
1030 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1034 client_mode_list = silc_buffer_alloc(len);
1035 silc_buffer_pull_tail(client_mode_list, len);
1036 silc_buffer_put(client_mode_list, tmp, len);
1038 /* Get founder key */
1039 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1041 silc_public_key_payload_decode(tmp, len, &founder_key);
1043 /* See whether we already have the channel. */
1044 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
1045 SILC_STRING_UTF8, 256, NULL);
1048 entry = silc_idlist_find_channel_by_name(server->local_list,
1049 channel_namec, &cache);
1051 /* Add new channel */
1053 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1054 (created == 0 ? "existing" : "created"), channel_name,
1055 silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL)));
1057 /* If the channel is found from global list we must move it to the
1059 entry = silc_idlist_find_channel_by_name(server->global_list,
1060 channel_namec, &cache);
1062 silc_idlist_del_channel(server->global_list, entry);
1064 /* Add the channel to our local list. */
1065 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1066 SILC_CHANNEL_MODE_NONE,
1067 silc_id_dup(SILC_ID_GET_ID(id),
1069 server->router, NULL, NULL, hmac);
1074 server->stat.my_channels++;
1075 server->stat.channels++;
1077 /* The entry exists. */
1079 /* If ID has changed, then update it to the cache too. */
1080 if (!SILC_ID_CHANNEL_COMPARE(entry->id, SILC_ID_GET_ID(id)))
1081 silc_idlist_replace_channel_id(server->local_list, entry->id,
1082 SILC_ID_GET_ID(id));
1084 entry->disabled = FALSE;
1086 /* Remove the founder auth data if the mode is not set but we have
1087 them in the entry */
1088 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1089 silc_pkcs_public_key_free(entry->founder_key);
1090 entry->founder_key = NULL;
1095 if (entry->founder_key)
1096 silc_pkcs_public_key_free(entry->founder_key);
1097 entry->founder_key = founder_key;
1101 if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1102 silc_free(entry->hmac_name);
1103 entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1106 /* Get the ban list */
1107 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1108 if (tmp && len > 2) {
1109 SilcArgumentPayload iargs;
1111 SILC_GET16_MSB(iargc, tmp);
1112 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1114 /* Delete old ban list */
1115 if (entry->ban_list)
1116 silc_hash_table_free(entry->ban_list);
1118 silc_hash_table_alloc(0, silc_hash_ptr,
1120 silc_server_inviteban_destruct, entry, TRUE);
1122 /* Add new ban list */
1123 silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1124 silc_argument_payload_free(iargs);
1128 /* Get the invite list */
1129 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1130 if (tmp && len > 2) {
1131 SilcArgumentPayload iargs;
1133 SILC_GET16_MSB(iargc, tmp);
1134 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1136 /* Delete old invite list */
1137 if (entry->invite_list)
1138 silc_hash_table_free(entry->invite_list);
1139 entry->invite_list =
1140 silc_hash_table_alloc(0, silc_hash_ptr,
1142 silc_server_inviteban_destruct, entry, TRUE);
1144 /* Add new invite list */
1145 silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1146 silc_argument_payload_free(iargs);
1151 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1153 silc_free(entry->topic);
1154 entry->topic = strdup(tmp);
1157 /* Get channel public key list */
1158 tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1159 if (tmp && server->server_type != SILC_ROUTER)
1160 silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1162 /* The the user limit */
1163 tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1164 if (tmp && len == 4)
1165 SILC_GET32_MSB(entry->user_limit, tmp);
1167 /* If channel was not created we know there is global users on the
1169 entry->global_users = (created == 0 ? TRUE : FALSE);
1171 /* If channel was just created the mask must be zero */
1172 if (!entry->global_users && mode)
1175 /* Save channel mode */
1178 /* Save channel key */
1180 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1181 silc_server_save_channel_key(server, keyp, entry);
1182 silc_buffer_free(keyp);
1185 /* Save the users to the channel */
1186 silc_server_save_users_on_channel(server, cmd->sock, entry,
1187 SILC_ID_GET_ID(id2), client_id_list,
1188 client_mode_list, list_count);
1189 entry->users_resolved = TRUE;
1192 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1194 silc_free(channel_namec);
1196 silc_hmac_free(hmac);
1197 silc_server_command_reply_free(cmd);
1200 silc_pkcs_public_key_free(founder_key);
1202 silc_buffer_free(client_id_list);
1203 if (client_mode_list)
1204 silc_buffer_free(client_mode_list);
1207 /* Received reply to STATS command. */
1209 SILC_SERVER_CMD_REPLY_FUNC(stats)
1211 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1212 SilcServer server = cmd->server;
1213 SilcStatus status, error;
1216 SilcBufferStruct buf;
1218 COMMAND_CHECK_STATUS;
1220 /* Get statistics structure */
1221 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1222 if (server->server_type != SILC_ROUTER && tmp) {
1223 silc_buffer_set(&buf, tmp, tmp_len);
1224 silc_buffer_unformat(&buf,
1225 SILC_STR_UI_INT(NULL),
1226 SILC_STR_UI_INT(NULL),
1227 SILC_STR_UI_INT(NULL),
1228 SILC_STR_UI_INT(NULL),
1229 SILC_STR_UI_INT(NULL),
1230 SILC_STR_UI_INT(NULL),
1231 SILC_STR_UI_INT(&server->stat.cell_clients),
1232 SILC_STR_UI_INT(&server->stat.cell_channels),
1233 SILC_STR_UI_INT(&server->stat.cell_servers),
1234 SILC_STR_UI_INT(&server->stat.clients),
1235 SILC_STR_UI_INT(&server->stat.channels),
1236 SILC_STR_UI_INT(&server->stat.servers),
1237 SILC_STR_UI_INT(&server->stat.routers),
1238 SILC_STR_UI_INT(&server->stat.server_ops),
1239 SILC_STR_UI_INT(&server->stat.router_ops),
1244 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1246 silc_server_command_reply_free(cmd);
1249 SILC_SERVER_CMD_REPLY_FUNC(users)
1251 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1252 SilcServer server = cmd->server;
1253 SilcStatus status, error;
1254 SilcChannelEntry channel;
1256 SilcBuffer client_id_list;
1257 SilcBuffer client_mode_list;
1260 SilcUInt32 list_count;
1262 COMMAND_CHECK_STATUS;
1264 /* Get channel ID */
1265 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1268 /* Get channel entry */
1269 channel = silc_idlist_find_channel_by_id(server->local_list,
1270 SILC_ID_GET_ID(id), NULL);
1272 channel = silc_idlist_find_channel_by_id(server->global_list,
1273 SILC_ID_GET_ID(id), NULL);
1277 if (server->server_type != SILC_SERVER)
1280 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1281 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1282 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1283 1, 5, idp->data, silc_buffer_len(idp));
1284 silc_buffer_free(idp);
1286 /* Register pending command callback. After we've received the channel
1287 information we will reprocess this command reply by re-calling this
1288 USERS command reply callback. */
1289 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1291 silc_server_command_reply_users, cmd);
1296 /* Get the list count */
1297 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1300 SILC_GET32_MSB(list_count, tmp);
1302 /* Get Client ID list */
1303 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1307 client_id_list = silc_buffer_alloc(tmp_len);
1308 silc_buffer_pull_tail(client_id_list, tmp_len);
1309 silc_buffer_put(client_id_list, tmp, tmp_len);
1311 /* Get client mode list */
1312 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1316 client_mode_list = silc_buffer_alloc(tmp_len);
1317 silc_buffer_pull_tail(client_mode_list, tmp_len);
1318 silc_buffer_put(client_mode_list, tmp, tmp_len);
1320 /* Save the users to the channel */
1321 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1322 client_id_list, client_mode_list,
1325 channel->global_users = silc_server_channel_has_global(channel);
1326 channel->users_resolved = TRUE;
1328 silc_buffer_free(client_id_list);
1329 silc_buffer_free(client_mode_list);
1332 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1334 silc_server_command_reply_free(cmd);
1337 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1339 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1340 SilcServer server = cmd->server;
1341 SilcStatus status, error;
1342 SilcClientEntry client = NULL;
1343 SilcServerEntry server_entry = NULL;
1344 SilcClientID client_id;
1345 SilcServerID server_id;
1348 SilcIDPayload idp = NULL;
1350 SilcPublicKey public_key = NULL;
1352 COMMAND_CHECK_STATUS;
1354 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1357 idp = silc_id_payload_parse(tmp, len);
1361 /* Get the public key payload */
1362 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1366 /* Decode the public key payload */
1367 if (!silc_public_key_payload_decode(tmp, len, &public_key))
1370 id_type = silc_id_payload_get_type(idp);
1371 if (id_type == SILC_ID_CLIENT) {
1372 silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
1374 client = silc_idlist_find_client_by_id(server->local_list, &client_id,
1377 client = silc_idlist_find_client_by_id(server->global_list,
1378 &client_id, TRUE, NULL);
1383 if (!client->data.public_key) {
1384 /* Add client's public key to repository */
1385 if (!silc_server_get_public_key_by_client(server, client, NULL))
1386 silc_skr_add_public_key_simple(server->repository,
1388 SILC_SKR_USAGE_IDENTIFICATION,
1390 client->data.public_key = public_key;
1393 } else if (id_type == SILC_ID_SERVER) {
1394 silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
1396 server_entry = silc_idlist_find_server_by_id(server->local_list,
1397 &server_id, TRUE, NULL);
1398 if (!server_entry) {
1399 server_entry = silc_idlist_find_server_by_id(server->global_list,
1400 &server_id, TRUE, NULL);
1405 server_entry->data.public_key = public_key;
1412 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1414 silc_id_payload_free(idp);
1416 silc_pkcs_public_key_free(public_key);
1418 silc_server_command_reply_free(cmd);
1421 SILC_SERVER_CMD_REPLY_FUNC(list)
1423 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1424 SilcServer server = cmd->server;
1425 SilcStatus status, error;
1427 SilcChannelEntry channel;
1428 SilcIDCacheEntry cache;
1429 unsigned char *tmp, *name, *namec = NULL, *topic;
1430 SilcUInt32 usercount = 0;
1431 SilcBool global_list = FALSE;
1433 COMMAND_CHECK_STATUS;
1435 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1438 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1439 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1440 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1442 SILC_GET32_MSB(usercount, tmp);
1444 namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
1449 /* Add the channel entry if we do not have it already */
1450 channel = silc_idlist_find_channel_by_name(server->local_list,
1453 channel = silc_idlist_find_channel_by_name(server->global_list,
1458 /* If router did not find such channel in its lists then this must
1459 be bogus channel or some router in the net is buggy. */
1460 if (server->server_type != SILC_SERVER)
1463 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1464 SILC_CHANNEL_MODE_NONE,
1465 silc_id_dup(SILC_ID_GET_ID(id),
1467 server->router, NULL, NULL, NULL);
1472 channel->user_count = usercount;
1475 silc_free(channel->topic);
1476 channel->topic = strdup(topic);
1479 /* Pending callbacks are not executed if this was an list entry */
1480 if (status != SILC_STATUS_OK &&
1481 status != SILC_STATUS_LIST_END) {
1482 silc_server_command_reply_free(cmd);
1487 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1490 silc_server_command_reply_free(cmd);
1493 SILC_SERVER_CMD_REPLY_FUNC(watch)
1495 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1496 SilcStatus status, error;
1498 COMMAND_CHECK_STATUS;
1501 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1503 silc_server_command_reply_free(cmd);
1506 SILC_SERVER_CMD_REPLY_FUNC(ping)
1508 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1509 SilcStatus status, error;
1511 COMMAND_CHECK_STATUS;
1514 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1516 silc_server_command_reply_free(cmd);