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));
264 /* Remove the old cache entry */
265 silc_idcache_del_by_context(global ? server->global_list->clients :
266 server->local_list->clients, client, NULL);
268 silc_free(client->nickname);
269 silc_free(client->username);
270 silc_free(client->userinfo);
271 silc_free(client->servername);
273 client->nickname = strdup(nick);
274 client->username = strdup(username);
275 client->userinfo = strdup(realname);
276 client->servername = servername[0] ? strdup(servername) : NULL;
278 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
279 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
281 /* Create new cache entry */
282 silc_idcache_add(global ? server->global_list->clients :
283 server->local_list->clients, nickname, client->id,
287 /* Save channel list if it was sent to us */
288 if (server->server_type == SILC_SERVER) {
289 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
290 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
292 SilcBufferStruct channels_buf, umodes_buf;
293 silc_buffer_set(&channels_buf, tmp, len);
294 silc_buffer_set(&umodes_buf, umodes, len2);
295 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
298 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
302 if (fingerprint && flen == sizeof(client->data.fingerprint))
303 memcpy(client->data.fingerprint, fingerprint, flen);
305 /* Take Requested Attributes if set. */
306 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
308 silc_free(client->attrs);
309 client->attrs = silc_memdup(tmp, len);
310 client->attrs_len = len;
312 /* Try to take public key from attributes if present and we don't have
313 the key already. Do this only on normal server. Routers do GETKEY
314 for all clients anyway. */
315 if (server->server_type != SILC_ROUTER && !client->data.public_key) {
316 SilcAttributePayload attr;
317 SilcAttributeObjPk pk;
318 unsigned char f[SILC_HASH_MAXLEN];
319 SilcDList attrs = silc_attribute_payload_parse(tmp, len);
321 SILC_LOG_DEBUG(("Take client public key from attributes"));
324 silc_dlist_start(attrs);
325 while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
326 if (silc_attribute_get_attribute(attr) ==
327 SILC_ATTRIBUTE_USER_PUBLIC_KEY) {
329 if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
332 /* Take only SILC public keys */
333 if (strcmp(pk.type, "silc-rsa")) {
339 /* Verify that the server provided fingerprint matches the key */
340 silc_hash_make(server->sha1hash, pk.data, pk.data_len, f);
341 if (memcmp(f, client->data.fingerprint, sizeof(f))) {
347 /* Save the public key. */
348 if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC,
349 pk.data, pk.data_len,
350 &client->data.public_key)) {
356 SILC_LOG_DEBUG(("Saved client public key from attributes"));
358 /* Add client's public key to repository */
359 if (!silc_server_get_public_key_by_client(server, client, NULL))
360 silc_skr_add_public_key_simple(server->repository,
361 client->data.public_key,
362 SILC_SKR_USAGE_IDENTIFICATION,
371 silc_attribute_payload_list_free(attrs);
379 /* Handle requested attributes reply in WHOIS from client */
382 silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd)
386 SilcClientEntry client = silc_packet_get_context(cmd->sock);
388 /* Take Requested Attributes if set. */
389 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
391 silc_free(client->attrs);
392 client->attrs = silc_memdup(tmp, len);
393 client->attrs_len = len;
396 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
401 /* Reiceved reply for WHOIS command. We sent the whois request to our
402 primary router, if we are normal server, and thus has now received reply
403 to the command. We will figure out what client originally sent us the
404 command and will send the reply to it. If we are router we will figure
405 out who server sent us the command and send reply to that one. */
407 SILC_SERVER_CMD_REPLY_FUNC(whois)
409 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
410 SilcIDListData idata = silc_packet_get_context(cmd->sock);
411 SilcStatus status, error;
413 COMMAND_CHECK_STATUS;
415 if (idata->conn_type != SILC_CONN_CLIENT) {
416 if (!silc_server_command_reply_whois_save(cmd))
419 if (!silc_server_command_reply_whois_save_client(cmd))
423 /* Pending callbacks are not executed if this was an list entry */
424 if (status != SILC_STATUS_OK &&
425 status != SILC_STATUS_LIST_END) {
426 silc_server_command_reply_free(cmd);
431 silc_server_command_process_error(cmd, error);
432 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
433 silc_server_command_reply_free(cmd);
437 silc_server_command_process_error(cmd, error);
438 silc_server_command_reply_free(cmd);
441 /* Caches the received WHOWAS information for a short period of time. */
444 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
446 SilcServer server = cmd->server;
447 SilcUInt32 len, id_len;
448 unsigned char *id_data;
449 char *nickname, *username, *realname;
451 SilcClientEntry client;
452 SilcIDCacheEntry cache = NULL;
453 char nick[128 + 1], servername[256 + 1], uname[128 + 1];
455 const char *hostname, *ip;
457 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
458 NULL, &hostname, &ip, NULL);
460 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
461 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
462 username = silc_argument_get_arg_type(cmd->args, 4, &len);
463 if (!id_data || !nickname || !username)
466 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
468 if (!silc_id_payload_parse_id(id_data, id_len, &id))
471 /* Check if we have this client cached already. */
473 client = silc_idlist_find_client_by_id(server->local_list,
477 client = silc_idlist_find_client_by_id(server->global_list,
484 /* If router did not find such Client ID in its lists then this must
485 be bogus client or some router in the net is buggy. */
486 if (server->server_type != SILC_SERVER)
489 /* Take hostname out of nick string if it includes it. */
490 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
493 /* We don't have that client anywhere, add it. The client is added
494 to global list since server didn't have it in the lists so it must be
496 client = silc_idlist_add_client(server->global_list,
497 strdup(nick), username,
499 silc_id_dup(SILC_ID_GET_ID(id),
501 silc_packet_get_context(cmd->sock), NULL);
503 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
507 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
508 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
509 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
510 client->servername = servername[0] ? strdup(servername) : NULL;
512 /* We have the client already, update the data */
515 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
517 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
520 SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOWAS reply "
522 hostname ? hostname : "", nick));
527 silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
528 if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128))
531 silc_free(client->nickname);
532 silc_free(client->username);
533 silc_free(client->servername);
535 client->nickname = strdup(nick);
536 client->username = strdup(username);
537 client->servername = servername[0] ? strdup(servername) : NULL;
538 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
539 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
541 /* Remove the old cache entry and create a new one */
542 silc_idcache_del_by_context(global ? server->global_list->clients :
543 server->local_list->clients, client, NULL);
544 silc_idcache_add(global ? server->global_list->clients :
545 server->local_list->clients, nickname, client->id,
549 /* If client is global and is not on any channel then add that we'll
550 expire the entry after a while. */
552 silc_idlist_find_client_by_id(server->global_list, client->id,
554 if (!silc_hash_table_count(client->channels))
555 silc_dlist_add(server->expired_clients, client);
561 /* Received reply for WHOWAS command. Cache the client information only for
562 a short period of time. */
564 SILC_SERVER_CMD_REPLY_FUNC(whowas)
566 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
567 SilcStatus status, error;
569 COMMAND_CHECK_STATUS;
571 if (!silc_server_command_reply_whowas_save(cmd))
574 /* Pending callbacks are not executed if this was an list entry */
575 if (status != SILC_STATUS_OK &&
576 status != SILC_STATUS_LIST_END) {
577 silc_server_command_reply_free(cmd);
582 silc_server_command_process_error(cmd, error);
583 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
584 silc_server_command_reply_free(cmd);
588 silc_server_command_process_error(cmd, error);
589 silc_server_command_reply_free(cmd);
592 /* Caches the received IDENTIFY information. */
595 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
597 SilcServer server = cmd->server;
598 SilcUInt32 len, id_len;
599 unsigned char *id_data;
601 SilcClientID client_id;
602 SilcServerID server_id;
603 SilcChannelID*channel_id;
604 SilcClientEntry client;
605 SilcServerEntry server_entry;
606 SilcChannelEntry channel;
609 SilcIDPayload idp = NULL;
612 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
615 idp = silc_id_payload_parse(id_data, id_len);
619 name = silc_argument_get_arg_type(cmd->args, 3, &len);
620 info = silc_argument_get_arg_type(cmd->args, 4, &len);
622 id_type = silc_id_payload_get_type(idp);
626 if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
629 SILC_LOG_DEBUG(("Received client information"));
631 client = silc_idlist_find_client_by_id(server->local_list,
632 &client_id, FALSE, NULL);
634 client = silc_idlist_find_client_by_id(server->global_list, &client_id,
639 /* If router did not find such Client ID in its lists then this must
640 be bogus client or some router in the net is buggy. */
641 if (server->server_type != SILC_SERVER)
646 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
648 /* We don't have that client anywhere, add it. The client is added
649 to global list since server didn't have it in the lists so it must be
651 client = silc_idlist_add_client(server->global_list,
652 nick[0] ? nick : NULL, info, NULL,
653 silc_id_dup(&client_id, SILC_ID_CLIENT),
654 silc_packet_get_context(cmd->sock),
657 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
661 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
662 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
663 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
665 /* We have the client already, update the data */
667 SILC_LOG_DEBUG(("Updating client data"));
671 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
674 name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
677 SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY "
682 /* Remove the old cache entry */
683 silc_idcache_del_by_context(global ? server->global_list->clients :
684 server->local_list->clients, client, NULL);
686 silc_free(client->nickname);
687 client->nickname = strdup(nick);
689 /* Add new cache entry */
690 silc_idcache_add(global ? server->global_list->clients :
691 server->local_list->clients, name, client->id,
696 silc_free(client->username);
697 client->username = strdup(info);
700 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
701 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
710 if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
713 SILC_LOG_DEBUG(("Received server information"));
715 server_entry = silc_idlist_find_server_by_id(server->local_list,
716 &server_id, FALSE, NULL);
718 server_entry = silc_idlist_find_server_by_id(server->global_list,
719 &server_id, FALSE, NULL);
721 /* If router did not find such Server ID in its lists then this must
722 be bogus server or some router in the net is buggy. */
723 if (server->server_type != SILC_SERVER)
726 /* We don't have that server anywhere, add it. */
727 server_entry = silc_idlist_add_server(server->global_list,
729 silc_id_dup(&server_id,
732 SILC_PRIMARY_ROUTE(server));
736 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
737 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
738 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
743 case SILC_ID_CHANNEL:
747 if (!silc_id_payload_get_id(idp, &channel_id, sizeof(channel_id)))
750 SILC_LOG_DEBUG(("Received channel information"));
752 /* Check channel name */
753 info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
758 channel = silc_idlist_find_channel_by_name(server->local_list,
761 channel = silc_idlist_find_channel_by_name(server->global_list,
764 /* If router did not find such Channel ID in its lists then this must
765 be bogus channel or some router in the net is buggy. */
766 if (server->server_type != SILC_SERVER) {
771 /* We don't have that channel anywhere, add it. */
772 channel = silc_idlist_add_channel(server->global_list, strdup(name),
773 SILC_CHANNEL_MODE_NONE,
774 silc_id_dup(&channel_id,
776 server->router, NULL, NULL, 0);
787 silc_id_payload_free(idp);
791 silc_id_payload_free(idp);
795 /* Received reply for forwarded IDENTIFY command. We have received the
796 requested identify information now and we will cache it. After this we
797 will call the pending command so that the requestee gets the information
800 SILC_SERVER_CMD_REPLY_FUNC(identify)
802 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
803 SilcStatus status, error;
805 COMMAND_CHECK_STATUS;
807 if (!silc_server_command_reply_identify_save(cmd))
810 /* Pending callbacks are not executed if this was an list entry */
811 if (status != SILC_STATUS_OK &&
812 status != SILC_STATUS_LIST_END) {
813 silc_server_command_reply_free(cmd);
818 silc_server_command_process_error(cmd, error);
819 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
820 silc_server_command_reply_free(cmd);
824 silc_server_command_process_error(cmd, error);
825 silc_server_command_reply_free(cmd);
828 /* Received reply fro INFO command. Cache the server and its information */
830 SILC_SERVER_CMD_REPLY_FUNC(info)
832 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
833 SilcServer server = cmd->server;
834 SilcStatus status, error;
835 SilcServerEntry entry;
838 unsigned char *tmp, *name;
840 COMMAND_CHECK_STATUS;
843 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
847 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
851 entry = silc_idlist_find_server_by_id(server->local_list,
855 entry = silc_idlist_find_server_by_id(server->global_list,
859 /* Add the server to global list */
860 entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
861 silc_id_dup(SILC_ID_GET_ID(id),
863 silc_packet_get_context(cmd->sock),
868 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
872 /* Get the info string */
873 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
877 entry->server_info = tmp ? strdup(tmp) : NULL;
880 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
882 silc_server_command_reply_free(cmd);
885 /* Received reply fro MOTD command. */
887 SILC_SERVER_CMD_REPLY_FUNC(motd)
889 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
890 SilcServer server = cmd->server;
891 SilcStatus status, error;
892 SilcServerEntry entry = NULL;
897 COMMAND_CHECK_STATUS;
900 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
903 entry = silc_idlist_find_server_by_id(server->local_list,
907 entry = silc_idlist_find_server_by_id(server->global_list,
913 /* If router did not find such Server ID in its lists then this must
914 be bogus client or some router in the net is buggy. */
915 if (server->server_type != SILC_SERVER)
919 cmd->server->stat.commands_sent++;
921 /* entry isn't known so we IDENTIFY it. otherwise the
922 silc_server_command_motd won't know about it and tell
923 the client that there is no such server */
924 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
925 buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
926 ++server->cmd_ident, 5,
927 1, NULL, 0, 2, NULL, 0,
928 3, NULL, 0, 4, NULL, 0,
930 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
931 SILC_PACKET_COMMAND, 0, buffer->data,
932 silc_buffer_len(buffer));
933 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
935 silc_server_command_reply_motd,
937 silc_buffer_free(buffer);
943 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
950 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
952 silc_server_command_reply_free(cmd);
958 /* Received reply for forwarded JOIN command. Router has created or joined
959 the client to the channel. We save some channel information locally
962 SILC_SERVER_CMD_REPLY_FUNC(join)
964 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
965 SilcServer server = cmd->server;
966 SilcIDCacheEntry cache = NULL;
967 SilcStatus status, error;
969 SilcChannelEntry entry;
970 SilcHmac hmac = NULL;
971 SilcUInt32 len, list_count;
972 char *channel_name, *channel_namec = NULL, *tmp;
973 SilcUInt32 mode, created;
974 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
975 SilcPublicKey founder_key = NULL;
977 COMMAND_CHECK_STATUS;
979 /* Get channel name */
980 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
985 if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id, NULL))
989 if (!silc_argument_get_decoded(cmd->args, 4, SILC_ARGUMENT_ID, &id2, NULL))
993 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
996 SILC_GET32_MSB(mode, tmp);
998 /* Get created boolean value */
999 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1002 SILC_GET32_MSB(created, tmp);
1003 if (created != 0 && created != 1)
1006 /* Get channel key */
1007 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
1009 keyp = silc_buffer_alloc(len);
1010 silc_buffer_pull_tail(keyp, silc_buffer_truelen(keyp));
1011 silc_buffer_put(keyp, tmp, len);
1015 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1017 if (!silc_hmac_alloc(tmp, NULL, &hmac))
1021 /* Get the list count */
1022 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1025 SILC_GET32_MSB(list_count, tmp);
1027 /* Get Client ID list */
1028 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1032 client_id_list = silc_buffer_alloc(len);
1033 silc_buffer_pull_tail(client_id_list, len);
1034 silc_buffer_put(client_id_list, tmp, len);
1036 /* Get client mode list */
1037 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1041 client_mode_list = silc_buffer_alloc(len);
1042 silc_buffer_pull_tail(client_mode_list, len);
1043 silc_buffer_put(client_mode_list, tmp, len);
1045 /* Get founder key */
1046 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1048 silc_public_key_payload_decode(tmp, len, &founder_key);
1050 /* See whether we already have the channel. */
1051 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
1052 SILC_STRING_UTF8, 256, NULL);
1055 entry = silc_idlist_find_channel_by_name(server->local_list,
1056 channel_namec, &cache);
1058 /* Add new channel */
1060 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1061 (created == 0 ? "existing" : "created"), channel_name,
1062 silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL)));
1064 /* If the channel is found from global list we must move it to the
1066 entry = silc_idlist_find_channel_by_name(server->global_list,
1067 channel_namec, &cache);
1069 silc_idlist_del_channel(server->global_list, entry);
1071 /* Add the channel to our local list. */
1072 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1073 SILC_CHANNEL_MODE_NONE,
1074 silc_id_dup(SILC_ID_GET_ID(id),
1076 server->router, NULL, NULL, hmac);
1081 server->stat.my_channels++;
1082 server->stat.channels++;
1084 /* The entry exists. */
1086 /* If ID has changed, then update it to the cache too. */
1087 if (!SILC_ID_CHANNEL_COMPARE(entry->id, SILC_ID_GET_ID(id)))
1088 silc_idlist_replace_channel_id(server->local_list, entry->id,
1089 SILC_ID_GET_ID(id));
1091 entry->disabled = FALSE;
1093 /* Remove the founder auth data if the mode is not set but we have
1094 them in the entry */
1095 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1096 silc_pkcs_public_key_free(entry->founder_key);
1097 entry->founder_key = NULL;
1102 if (entry->founder_key)
1103 silc_pkcs_public_key_free(entry->founder_key);
1104 entry->founder_key = founder_key;
1108 if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1109 silc_free(entry->hmac_name);
1110 entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1113 /* Get the ban list */
1114 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1115 if (tmp && len > 2) {
1116 SilcArgumentPayload iargs;
1118 SILC_GET16_MSB(iargc, tmp);
1119 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1121 /* Delete old ban list */
1122 if (entry->ban_list)
1123 silc_hash_table_free(entry->ban_list);
1125 silc_hash_table_alloc(0, silc_hash_ptr,
1127 silc_server_inviteban_destruct, entry, TRUE);
1129 /* Add new ban list */
1130 silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1131 silc_argument_payload_free(iargs);
1135 /* Get the invite list */
1136 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1137 if (tmp && len > 2) {
1138 SilcArgumentPayload iargs;
1140 SILC_GET16_MSB(iargc, tmp);
1141 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1143 /* Delete old invite list */
1144 if (entry->invite_list)
1145 silc_hash_table_free(entry->invite_list);
1146 entry->invite_list =
1147 silc_hash_table_alloc(0, silc_hash_ptr,
1149 silc_server_inviteban_destruct, entry, TRUE);
1151 /* Add new invite list */
1152 silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1153 silc_argument_payload_free(iargs);
1158 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1160 silc_free(entry->topic);
1161 entry->topic = strdup(tmp);
1164 /* Get channel public key list */
1165 tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1166 if (tmp && server->server_type != SILC_ROUTER)
1167 silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1169 /* The the user limit */
1170 tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1171 if (tmp && len == 4)
1172 SILC_GET32_MSB(entry->user_limit, tmp);
1174 /* If channel was not created we know there is global users on the
1176 entry->global_users = (created == 0 ? TRUE : FALSE);
1178 /* If channel was just created the mask must be zero */
1179 if (!entry->global_users && mode)
1182 /* Save channel mode */
1185 /* Save channel key */
1187 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1188 silc_server_save_channel_key(server, keyp, entry);
1189 silc_buffer_free(keyp);
1192 /* Save the users to the channel */
1193 silc_server_save_users_on_channel(server, cmd->sock, entry,
1194 SILC_ID_GET_ID(id2), client_id_list,
1195 client_mode_list, list_count);
1196 entry->users_resolved = TRUE;
1199 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1201 silc_free(channel_namec);
1203 silc_hmac_free(hmac);
1204 silc_server_command_reply_free(cmd);
1206 silc_pkcs_public_key_free(founder_key);
1208 silc_buffer_free(client_id_list);
1209 if (client_mode_list)
1210 silc_buffer_free(client_mode_list);
1213 /* Received reply to STATS command. */
1215 SILC_SERVER_CMD_REPLY_FUNC(stats)
1217 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1218 SilcServer server = cmd->server;
1219 SilcStatus status, error;
1222 SilcBufferStruct buf;
1224 COMMAND_CHECK_STATUS;
1226 /* Get statistics structure */
1227 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1228 if (server->server_type != SILC_ROUTER && tmp) {
1229 silc_buffer_set(&buf, tmp, tmp_len);
1230 silc_buffer_unformat(&buf,
1231 SILC_STR_UI_INT(NULL),
1232 SILC_STR_UI_INT(NULL),
1233 SILC_STR_UI_INT(NULL),
1234 SILC_STR_UI_INT(NULL),
1235 SILC_STR_UI_INT(NULL),
1236 SILC_STR_UI_INT(NULL),
1237 SILC_STR_UI_INT(&server->stat.cell_clients),
1238 SILC_STR_UI_INT(&server->stat.cell_channels),
1239 SILC_STR_UI_INT(&server->stat.cell_servers),
1240 SILC_STR_UI_INT(&server->stat.clients),
1241 SILC_STR_UI_INT(&server->stat.channels),
1242 SILC_STR_UI_INT(&server->stat.servers),
1243 SILC_STR_UI_INT(&server->stat.routers),
1244 SILC_STR_UI_INT(&server->stat.server_ops),
1245 SILC_STR_UI_INT(&server->stat.router_ops),
1250 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1252 silc_server_command_reply_free(cmd);
1255 SILC_SERVER_CMD_REPLY_FUNC(users)
1257 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1258 SilcServer server = cmd->server;
1259 SilcStatus status, error;
1260 SilcChannelEntry channel;
1262 SilcBuffer client_id_list;
1263 SilcBuffer client_mode_list;
1266 SilcUInt32 list_count;
1268 COMMAND_CHECK_STATUS;
1270 /* Get channel ID */
1271 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1274 /* Get channel entry */
1275 channel = silc_idlist_find_channel_by_id(server->local_list,
1276 SILC_ID_GET_ID(id), NULL);
1278 channel = silc_idlist_find_channel_by_id(server->global_list,
1279 SILC_ID_GET_ID(id), NULL);
1283 if (server->server_type != SILC_SERVER)
1286 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1287 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1288 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1289 1, 5, idp->data, silc_buffer_len(idp));
1290 silc_buffer_free(idp);
1292 /* Register pending command callback. After we've received the channel
1293 information we will reprocess this command reply by re-calling this
1294 USERS command reply callback. */
1295 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1297 silc_server_command_reply_users, cmd);
1302 /* Get the list count */
1303 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1306 SILC_GET32_MSB(list_count, tmp);
1308 /* Get Client ID list */
1309 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1313 client_id_list = silc_buffer_alloc(tmp_len);
1314 silc_buffer_pull_tail(client_id_list, tmp_len);
1315 silc_buffer_put(client_id_list, tmp, tmp_len);
1317 /* Get client mode list */
1318 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1322 client_mode_list = silc_buffer_alloc(tmp_len);
1323 silc_buffer_pull_tail(client_mode_list, tmp_len);
1324 silc_buffer_put(client_mode_list, tmp, tmp_len);
1326 /* Save the users to the channel */
1327 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1328 client_id_list, client_mode_list,
1331 channel->global_users = silc_server_channel_has_global(channel);
1332 channel->users_resolved = TRUE;
1334 silc_buffer_free(client_id_list);
1335 silc_buffer_free(client_mode_list);
1338 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1340 silc_server_command_reply_free(cmd);
1343 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1345 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1346 SilcServer server = cmd->server;
1347 SilcStatus status, error;
1348 SilcClientEntry client = NULL;
1349 SilcServerEntry server_entry = NULL;
1350 SilcClientID client_id;
1351 SilcServerID server_id;
1354 SilcIDPayload idp = NULL;
1356 SilcPublicKey public_key = NULL;
1358 COMMAND_CHECK_STATUS;
1360 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1363 idp = silc_id_payload_parse(tmp, len);
1367 /* Get the public key payload */
1368 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1372 /* Decode the public key payload */
1373 if (!silc_public_key_payload_decode(tmp, len, &public_key))
1376 id_type = silc_id_payload_get_type(idp);
1377 if (id_type == SILC_ID_CLIENT) {
1378 silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
1380 client = silc_idlist_find_client_by_id(server->local_list, &client_id,
1383 client = silc_idlist_find_client_by_id(server->global_list,
1384 &client_id, TRUE, NULL);
1389 if (!client->data.public_key) {
1390 /* Add client's public key to repository */
1391 if (!silc_server_get_public_key_by_client(server, client, NULL))
1392 silc_skr_add_public_key_simple(server->repository,
1394 SILC_SKR_USAGE_IDENTIFICATION,
1396 client->data.public_key = public_key;
1399 } else if (id_type == SILC_ID_SERVER) {
1400 silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
1402 server_entry = silc_idlist_find_server_by_id(server->local_list,
1403 &server_id, TRUE, NULL);
1404 if (!server_entry) {
1405 server_entry = silc_idlist_find_server_by_id(server->global_list,
1406 &server_id, TRUE, NULL);
1411 server_entry->data.public_key = public_key;
1418 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1420 silc_id_payload_free(idp);
1422 silc_pkcs_public_key_free(public_key);
1424 silc_server_command_reply_free(cmd);
1427 SILC_SERVER_CMD_REPLY_FUNC(list)
1429 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1430 SilcServer server = cmd->server;
1431 SilcStatus status, error;
1433 SilcChannelEntry channel;
1434 SilcIDCacheEntry cache;
1435 unsigned char *tmp, *name, *namec = NULL, *topic;
1436 SilcUInt32 usercount = 0;
1437 SilcBool global_list = FALSE;
1439 COMMAND_CHECK_STATUS;
1441 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1444 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1445 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1446 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1448 SILC_GET32_MSB(usercount, tmp);
1450 namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
1455 /* Add the channel entry if we do not have it already */
1456 channel = silc_idlist_find_channel_by_name(server->local_list,
1459 channel = silc_idlist_find_channel_by_name(server->global_list,
1464 /* If router did not find such channel in its lists then this must
1465 be bogus channel or some router in the net is buggy. */
1466 if (server->server_type != SILC_SERVER)
1469 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1470 SILC_CHANNEL_MODE_NONE,
1471 silc_id_dup(SILC_ID_GET_ID(id),
1473 server->router, NULL, NULL, NULL);
1478 channel->user_count = usercount;
1481 silc_free(channel->topic);
1482 channel->topic = strdup(topic);
1485 /* Pending callbacks are not executed if this was an list entry */
1486 if (status != SILC_STATUS_OK &&
1487 status != SILC_STATUS_LIST_END) {
1488 silc_server_command_reply_free(cmd);
1493 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1496 silc_server_command_reply_free(cmd);
1499 SILC_SERVER_CMD_REPLY_FUNC(watch)
1501 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1502 SilcStatus status, error;
1504 COMMAND_CHECK_STATUS;
1507 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1509 silc_server_command_reply_free(cmd);
1512 SILC_SERVER_CMD_REPLY_FUNC(ping)
1514 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1515 SilcStatus status, error;
1517 COMMAND_CHECK_STATUS;
1520 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1522 silc_server_command_reply_free(cmd);