5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 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; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
24 #include "command_reply.h"
26 /* All functions that call the COMMAND_CHECK_STATUS macros must have
27 out: and err: goto labels. */
29 #define COMMAND_CHECK_STATUS \
31 SILC_LOG_DEBUG(("Start")); \
32 if (!silc_command_get_status(cmd->payload, &status, &error)) { \
33 if (SILC_STATUS_IS_ERROR(status)) \
35 if (status == SILC_STATUS_LIST_END) \
41 /* Server command reply list. Not all commands have reply function as
42 they are never sent by server. More maybe added later if need appears. */
43 SilcServerCommandReply silc_command_reply_list[] =
45 SILC_SERVER_CMD_REPLY(whois, WHOIS),
46 SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
47 SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
48 SILC_SERVER_CMD_REPLY(info, INFO),
49 SILC_SERVER_CMD_REPLY(motd, MOTD),
50 SILC_SERVER_CMD_REPLY(join, JOIN),
51 SILC_SERVER_CMD_REPLY(stats, STATS),
52 SILC_SERVER_CMD_REPLY(users, USERS),
53 SILC_SERVER_CMD_REPLY(getkey, GETKEY),
54 SILC_SERVER_CMD_REPLY(list, LIST),
59 /* Process received command reply. */
61 void silc_server_command_reply_process(SilcServer server,
62 SilcSocketConnection sock,
65 SilcServerCommandReply *cmd;
66 SilcServerCommandReplyContext ctx;
67 SilcCommandPayload payload;
71 SILC_LOG_DEBUG(("Start"));
73 /* Get command reply payload from packet */
74 payload = silc_command_payload_parse(buffer->data, buffer->len);
76 /* Silently ignore bad reply packet */
77 SILC_LOG_DEBUG(("Bad command reply packet"));
81 /* Allocate command reply context. This must be free'd by the
82 command reply routine receiving it. */
83 ctx = silc_calloc(1, sizeof(*ctx));
85 ctx->sock = silc_socket_dup(sock);
86 ctx->payload = payload;
87 ctx->args = silc_command_get_args(ctx->payload);
88 ident = silc_command_get_ident(ctx->payload);
90 /* Check for pending commands and mark to be exeucted */
92 silc_server_command_pending_check(server, ctx,
93 silc_command_get(ctx->payload),
94 ident, &ctx->callbacks_count);
96 /* Execute command reply */
97 command = silc_command_get(ctx->payload);
98 for (cmd = silc_command_reply_list; cmd->cb; cmd++)
99 if (cmd->cmd == command)
102 if (cmd == NULL || !cmd->cb) {
103 silc_server_command_reply_free(ctx);
110 /* Free command reply context and its internals. */
112 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
115 silc_command_payload_free(cmd->payload);
117 silc_socket_free(cmd->sock); /* Decrease the reference counter */
118 silc_free(cmd->callbacks);
124 silc_server_command_process_error(SilcServerCommandReplyContext cmd,
127 SilcServer server = cmd->server;
129 /* If we received notify for invalid ID we'll remove the ID if we
131 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
132 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
133 SilcClientEntry client;
135 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
137 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
139 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
140 "the entry from cache"));
141 client = silc_idlist_find_client_by_id(server->global_list,
142 client_id, FALSE, NULL);
144 silc_server_remove_from_channels(server, NULL, client, TRUE,
146 silc_idlist_del_data(client);
147 silc_idlist_del_client(server->global_list, client);
149 silc_free(client_id);
155 /* Caches the received WHOIS information. */
158 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
160 SilcServer server = cmd->server;
161 unsigned char *tmp, *id_data, *umodes;
162 char *nickname, *username, *realname, *servername = NULL;
163 unsigned char *fingerprint;
164 SilcClientID *client_id;
165 SilcClientEntry client;
166 SilcIDCacheEntry cache = NULL;
169 SilcUInt32 mode = 0, len, len2, id_len, flen;
171 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
172 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
173 username = silc_argument_get_arg_type(cmd->args, 4, &len);
174 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
175 if (!id_data || !nickname || !username || !realname)
178 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
180 SILC_GET32_MSB(mode, tmp);
182 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
186 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
188 /* Check if we have this client cached already. */
190 client = silc_idlist_find_client_by_id(server->local_list, client_id,
193 client = silc_idlist_find_client_by_id(server->global_list, client_id,
199 /* If router did not find such Client ID in its lists then this must
200 be bogus client or some router in the net is buggy. */
201 if (server->server_type != SILC_SERVER)
204 /* Take hostname out of nick string if it includes it. */
205 silc_parse_userfqdn(nickname, &nick, &servername);
207 /* We don't have that client anywhere, add it. The client is added
208 to global list since server didn't have it in the lists so it must be
210 client = silc_idlist_add_client(server->global_list, nick,
212 strdup(realname), client_id,
213 cmd->sock->user_data, NULL, 0);
215 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
219 client->data.status |=
220 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
221 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
223 client->servername = servername;
225 /* We have the client already, update the data */
227 SILC_LOG_DEBUG(("Updating client data"));
229 /* Take hostname out of nick string if it includes it. */
230 silc_parse_userfqdn(nickname, &nick, &servername);
232 /* Remove the old cache entry */
233 silc_idcache_del_by_context(global ? server->global_list->clients :
234 server->local_list->clients, client);
236 silc_free(client->nickname);
237 silc_free(client->username);
238 silc_free(client->userinfo);
239 silc_free(client->servername);
241 client->nickname = nick;
242 client->username = strdup(username);
243 client->userinfo = strdup(realname);
244 client->servername = servername;
246 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
247 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
249 /* Create new cache entry */
250 silc_idcache_add(global ? server->global_list->clients :
251 server->local_list->clients, nick, client->id,
253 silc_free(client_id);
256 /* Save channel list if it was sent to us */
257 if (server->server_type == SILC_SERVER) {
258 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
259 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
261 SilcBufferStruct channels_buf, umodes_buf;
262 silc_buffer_set(&channels_buf, tmp, len);
263 silc_buffer_set(&umodes_buf, umodes, len2);
264 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
267 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
270 /* If client is global and is not on any channel then add that we'll
271 expire the entry after a while. */
273 silc_idlist_find_client_by_id(server->global_list, client->id,
275 if (!silc_hash_table_count(client->channels))
276 cache->expire = time(NULL) + 300;
282 if (fingerprint && flen == sizeof(client->data.fingerprint))
283 memcpy(client->data.fingerprint, fingerprint, flen);
288 /* Reiceved reply for WHOIS command. We sent the whois request to our
289 primary router, if we are normal server, and thus has now received reply
290 to the command. We will figure out what client originally sent us the
291 command and will send the reply to it. If we are router we will figure
292 out who server sent us the command and send reply to that one. */
294 SILC_SERVER_CMD_REPLY_FUNC(whois)
296 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
297 SilcStatus status, error;
299 COMMAND_CHECK_STATUS;
301 if (!silc_server_command_reply_whois_save(cmd))
304 /* Pending callbacks are not executed if this was an list entry */
305 if (status != SILC_STATUS_OK &&
306 status != SILC_STATUS_LIST_END) {
307 silc_server_command_reply_free(cmd);
312 silc_server_command_process_error(cmd, error);
313 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
314 silc_server_command_reply_free(cmd);
318 silc_server_command_process_error(cmd, error);
319 silc_server_command_reply_free(cmd);
322 /* Caches the received WHOWAS information for a short period of time. */
325 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
327 SilcServer server = cmd->server;
328 SilcUInt32 len, id_len;
329 unsigned char *id_data;
330 char *nickname, *username, *realname, *servername = NULL;
331 SilcClientID *client_id;
332 SilcClientEntry client;
333 SilcIDCacheEntry cache = NULL;
337 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
338 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
339 username = silc_argument_get_arg_type(cmd->args, 4, &len);
340 if (!id_data || !nickname || !username)
343 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
345 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
349 /* Check if we have this client cached already. */
351 client = silc_idlist_find_client_by_id(server->local_list, client_id,
354 client = silc_idlist_find_client_by_id(server->global_list,
355 client_id, FALSE, &cache);
360 /* If router did not find such Client ID in its lists then this must
361 be bogus client or some router in the net is buggy. */
362 if (server->server_type != SILC_SERVER)
365 /* Take hostname out of nick string if it includes it. */
366 silc_parse_userfqdn(nickname, &nick, &servername);
368 /* We don't have that client anywhere, add it. The client is added
369 to global list since server didn't have it in the lists so it must be
371 client = silc_idlist_add_client(server->global_list, nick,
372 strdup(username), strdup(realname),
373 silc_id_dup(client_id, SILC_ID_CLIENT),
374 cmd->sock->user_data, NULL,
375 SILC_ID_CACHE_EXPIRE_DEF);
377 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
381 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
382 client->servername = servername;
384 /* We have the client already, update the data */
386 /* Take hostname out of nick string if it includes it. */
387 silc_parse_userfqdn(nickname, &nick, &servername);
389 silc_free(client->nickname);
390 silc_free(client->username);
392 client->nickname = nick;
393 client->username = strdup(username);
394 client->servername = servername;
396 /* Remove the old cache entry and create a new one */
397 silc_idcache_del_by_context(global ? server->global_list->clients :
398 server->local_list->clients, client);
399 silc_idcache_add(global ? server->global_list->clients :
400 server->local_list->clients, nick, client->id,
404 silc_free(client_id);
409 /* Received reply for WHOWAS command. Cache the client information only for
410 a short period of time. */
412 SILC_SERVER_CMD_REPLY_FUNC(whowas)
414 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
415 SilcStatus status, error;
417 COMMAND_CHECK_STATUS;
419 if (!silc_server_command_reply_whowas_save(cmd))
422 /* Pending callbacks are not executed if this was an list entry */
423 if (status != SILC_STATUS_OK &&
424 status != SILC_STATUS_LIST_END) {
425 silc_server_command_reply_free(cmd);
430 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
432 silc_server_command_reply_free(cmd);
435 /* Caches the received IDENTIFY information. */
438 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
440 SilcServer server = cmd->server;
441 SilcUInt32 len, id_len;
442 unsigned char *id_data;
444 SilcClientID *client_id = NULL;
445 SilcServerID *server_id = NULL;
446 SilcChannelID *channel_id = NULL;
447 SilcClientEntry client;
448 SilcServerEntry server_entry;
449 SilcChannelEntry channel;
452 SilcIDPayload idp = NULL;
456 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
459 idp = silc_id_payload_parse(id_data, id_len);
463 name = silc_argument_get_arg_type(cmd->args, 3, &len);
464 info = silc_argument_get_arg_type(cmd->args, 4, &len);
466 id_type = silc_id_payload_get_type(idp);
470 client_id = silc_id_payload_get_id(idp);
474 SILC_LOG_DEBUG(("Received client information"));
476 client = silc_idlist_find_client_by_id(server->local_list,
477 client_id, FALSE, NULL);
479 client = silc_idlist_find_client_by_id(server->global_list, client_id,
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)
491 silc_parse_userfqdn(name, &nick, NULL);
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, nick,
497 info ? strdup(info) : NULL, NULL,
498 client_id, cmd->sock->user_data,
499 NULL, time(NULL) + 300);
501 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
504 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
505 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
506 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
508 /* We have the client already, update the data */
510 SILC_LOG_DEBUG(("Updating client data"));
514 silc_parse_userfqdn(name, &nick, NULL);
516 /* Remove the old cache entry */
517 silc_idcache_del_by_context(global ? server->global_list->clients :
518 server->local_list->clients, client);
520 silc_free(client->nickname);
521 client->nickname = nick;
525 silc_free(client->username);
526 client->username = strdup(info);
529 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
530 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
533 /* Add new cache entry */
534 silc_idcache_add(global ? server->global_list->clients :
535 server->local_list->clients, nick, client->id,
536 client, expire, NULL);
539 /* If client is global and is not on any channel then add that we'll
540 expire the entry after a while. */
541 if (global && server->server_type == SILC_SERVER) {
542 SilcIDCacheEntry cache = NULL;
543 silc_idlist_find_client_by_id(server->global_list, client->id,
545 if (!silc_hash_table_count(client->channels))
546 cache->expire = time(NULL) + 300;
551 silc_free(client_id);
560 server_id = silc_id_payload_get_id(idp);
564 SILC_LOG_DEBUG(("Received server information"));
566 server_entry = silc_idlist_find_server_by_id(server->local_list,
567 server_id, FALSE, NULL);
569 server_entry = silc_idlist_find_server_by_id(server->global_list,
570 server_id, FALSE, NULL);
572 /* If router did not find such Server ID in its lists then this must
573 be bogus server or some router in the net is buggy. */
574 if (server->server_type != SILC_SERVER)
577 /* We don't have that server anywhere, add it. */
578 server_entry = silc_idlist_add_server(server->global_list,
580 server_id, server->router,
581 SILC_PRIMARY_ROUTE(server));
583 silc_free(server_id);
586 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
587 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
588 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
592 silc_free(server_id);
595 case SILC_ID_CHANNEL:
599 channel_id = silc_id_payload_get_id(idp);
603 SILC_LOG_DEBUG(("Received channel information"));
605 channel = silc_idlist_find_channel_by_name(server->local_list,
608 channel = silc_idlist_find_channel_by_name(server->global_list,
611 /* If router did not find such Channel ID in its lists then this must
612 be bogus channel or some router in the net is buggy. */
613 if (server->server_type != SILC_SERVER)
616 /* We don't have that channel anywhere, add it. */
617 channel = silc_idlist_add_channel(server->global_list, strdup(name),
618 SILC_CHANNEL_MODE_NONE, channel_id,
619 server->router, NULL, NULL, 0);
621 silc_free(channel_id);
627 silc_free(channel_id);
631 silc_id_payload_free(idp);
635 silc_id_payload_free(idp);
639 /* Received reply for forwarded IDENTIFY command. We have received the
640 requested identify information now and we will cache it. After this we
641 will call the pending command so that the requestee gets the information
644 SILC_SERVER_CMD_REPLY_FUNC(identify)
646 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
647 SilcStatus status, error;
649 COMMAND_CHECK_STATUS;
651 if (!silc_server_command_reply_identify_save(cmd))
654 /* Pending callbacks are not executed if this was an list entry */
655 if (status != SILC_STATUS_OK &&
656 status != SILC_STATUS_LIST_END) {
657 silc_server_command_reply_free(cmd);
662 silc_server_command_process_error(cmd, error);
663 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
664 silc_server_command_reply_free(cmd);
668 silc_server_command_process_error(cmd, error);
669 silc_server_command_reply_free(cmd);
672 /* Received reply fro INFO command. Cache the server and its information */
674 SILC_SERVER_CMD_REPLY_FUNC(info)
676 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
677 SilcServer server = cmd->server;
678 SilcStatus status, error;
679 SilcServerEntry entry;
680 SilcServerID *server_id;
682 unsigned char *tmp, *name;
684 COMMAND_CHECK_STATUS;
687 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
690 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
695 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
699 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
702 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
705 /* Add the server to global list */
706 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
707 entry = silc_idlist_add_server(server->global_list, name, 0,
708 server_id, cmd->sock->user_data,
711 silc_free(server_id);
714 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
718 /* Get the info string */
719 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
723 entry->server_info = tmp ? strdup(tmp) : NULL;
726 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
728 silc_server_command_reply_free(cmd);
731 /* Received reply fro MOTD command. */
733 SILC_SERVER_CMD_REPLY_FUNC(motd)
735 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
736 SilcServer server = cmd->server;
737 SilcStatus status, error;
738 SilcServerEntry entry = NULL;
739 SilcServerID *server_id;
743 COMMAND_CHECK_STATUS;
746 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
749 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
753 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
756 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
763 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
770 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
772 silc_server_command_reply_free(cmd);
778 /* Received reply for forwarded JOIN command. Router has created or joined
779 the client to the channel. We save some channel information locally
782 SILC_SERVER_CMD_REPLY_FUNC(join)
784 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
785 SilcServer server = cmd->server;
786 SilcIDCacheEntry cache = NULL;
787 SilcStatus status, error;
789 SilcClientID *client_id = NULL;
790 SilcChannelEntry entry;
791 SilcHmac hmac = NULL;
792 SilcUInt32 id_len, len, list_count;
793 unsigned char *id_string;
794 char *channel_name, *tmp;
795 SilcUInt32 mode, created;
796 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
797 SilcPublicKey founder_key = NULL;
799 COMMAND_CHECK_STATUS;
801 /* Get channel name */
802 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
807 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
812 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
815 client_id = silc_id_payload_parse_id(tmp, len, NULL);
820 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
823 SILC_GET32_MSB(mode, tmp);
825 /* Get created boolean value */
826 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
829 SILC_GET32_MSB(created, tmp);
830 if (created != 0 && created != 1)
833 /* Get channel key */
834 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
836 keyp = silc_buffer_alloc(len);
837 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
838 silc_buffer_put(keyp, tmp, len);
841 /* Parse the Channel ID */
842 id = silc_id_payload_parse_id(id_string, id_len, NULL);
847 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
849 if (!silc_hmac_alloc(tmp, NULL, &hmac))
853 /* Get the list count */
854 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
857 SILC_GET32_MSB(list_count, tmp);
859 /* Get Client ID list */
860 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
864 client_id_list = silc_buffer_alloc(len);
865 silc_buffer_pull_tail(client_id_list, len);
866 silc_buffer_put(client_id_list, tmp, len);
868 /* Get client mode list */
869 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
873 client_mode_list = silc_buffer_alloc(len);
874 silc_buffer_pull_tail(client_mode_list, len);
875 silc_buffer_put(client_mode_list, tmp, len);
877 /* Get founder key */
878 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
880 silc_pkcs_public_key_decode(tmp, len, &founder_key);
882 /* See whether we already have the channel. */
883 entry = silc_idlist_find_channel_by_name(server->local_list,
884 channel_name, &cache);
886 /* Add new channel */
888 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
889 (created == 0 ? "existing" : "created"), channel_name,
890 silc_id_render(id, SILC_ID_CHANNEL)));
892 /* If the channel is found from global list we must move it to the
894 entry = silc_idlist_find_channel_by_name(server->global_list,
895 channel_name, &cache);
897 silc_idlist_del_channel(server->global_list, entry);
899 /* Add the channel to our local list. */
900 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
901 SILC_CHANNEL_MODE_NONE, id,
902 server->router, NULL, hmac, 0);
907 server->stat.my_channels++;
908 server->stat.channels++;
910 /* The entry exists. */
912 /* If ID has changed, then update it to the cache too. */
913 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
914 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
916 entry->disabled = FALSE;
918 /* Remove the founder auth data if the mode is not set but we have
920 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
921 silc_pkcs_public_key_free(entry->founder_key);
922 entry->founder_key = NULL;
927 if (entry->founder_key)
928 silc_pkcs_public_key_free(entry->founder_key);
929 entry->founder_key = founder_key;
933 if (entry->hmac_name && hmac) {
934 silc_free(entry->hmac_name);
935 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
938 /* Get the ban list */
939 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
941 silc_free(entry->ban_list);
942 entry->ban_list = silc_memdup(tmp, len);
945 /* Get the invite list */
946 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
948 silc_free(entry->invite_list);
949 entry->invite_list = silc_memdup(tmp, len);
953 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
955 silc_free(entry->topic);
956 entry->topic = strdup(tmp);
959 /* If channel was not created we know there is global users on the
961 entry->global_users = (created == 0 ? TRUE : FALSE);
963 /* If channel was just created the mask must be zero */
964 if (!entry->global_users && mode) {
965 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
966 "new channel, forcing it to zero", cmd->sock->hostname));
970 /* Save channel mode */
973 /* Save channel key */
975 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
976 silc_server_save_channel_key(server, keyp, entry);
977 silc_buffer_free(keyp);
980 /* Save the users to the channel */
981 silc_server_save_users_on_channel(server, cmd->sock, entry,
982 client_id, client_id_list,
983 client_mode_list, list_count);
984 entry->users_resolved = TRUE;
987 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
989 silc_free(client_id);
990 silc_server_command_reply_free(cmd);
992 silc_pkcs_public_key_free(founder_key);
994 silc_buffer_free(client_id_list);
995 if (client_mode_list)
996 silc_buffer_free(client_mode_list);
999 /* Received reply to STATS command. */
1001 SILC_SERVER_CMD_REPLY_FUNC(stats)
1003 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1004 SilcServer server = cmd->server;
1005 SilcStatus status, error;
1008 SilcBufferStruct buf;
1010 COMMAND_CHECK_STATUS;
1012 /* Get statistics structure */
1013 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1014 if (server->server_type == SILC_SERVER && tmp) {
1015 silc_buffer_set(&buf, tmp, tmp_len);
1016 silc_buffer_unformat(&buf,
1017 SILC_STR_UI_INT(NULL),
1018 SILC_STR_UI_INT(NULL),
1019 SILC_STR_UI_INT(NULL),
1020 SILC_STR_UI_INT(NULL),
1021 SILC_STR_UI_INT(NULL),
1022 SILC_STR_UI_INT(NULL),
1023 SILC_STR_UI_INT(&server->stat.cell_clients),
1024 SILC_STR_UI_INT(&server->stat.cell_channels),
1025 SILC_STR_UI_INT(&server->stat.cell_servers),
1026 SILC_STR_UI_INT(&server->stat.clients),
1027 SILC_STR_UI_INT(&server->stat.channels),
1028 SILC_STR_UI_INT(&server->stat.servers),
1029 SILC_STR_UI_INT(&server->stat.routers),
1030 SILC_STR_UI_INT(&server->stat.server_ops),
1031 SILC_STR_UI_INT(&server->stat.router_ops),
1036 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1038 silc_server_command_reply_free(cmd);
1041 SILC_SERVER_CMD_REPLY_FUNC(users)
1043 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1044 SilcServer server = cmd->server;
1045 SilcStatus status, error;
1046 SilcChannelEntry channel;
1047 SilcChannelID *channel_id = NULL;
1048 SilcBuffer client_id_list;
1049 SilcBuffer client_mode_list;
1052 SilcUInt32 list_count;
1054 COMMAND_CHECK_STATUS;
1056 /* Get channel ID */
1057 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1060 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1064 /* Get channel entry */
1065 channel = silc_idlist_find_channel_by_id(server->local_list,
1068 channel = silc_idlist_find_channel_by_id(server->global_list,
1073 if (server->server_type != SILC_SERVER)
1076 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1077 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1078 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1079 1, 5, idp->data, idp->len);
1080 silc_buffer_free(idp);
1082 /* Register pending command callback. After we've received the channel
1083 information we will reprocess this command reply by re-calling this
1084 USERS command reply callback. */
1085 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1087 silc_server_command_reply_users, cmd);
1092 /* Get the list count */
1093 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1096 SILC_GET32_MSB(list_count, tmp);
1098 /* Get Client ID list */
1099 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1103 client_id_list = silc_buffer_alloc(tmp_len);
1104 silc_buffer_pull_tail(client_id_list, tmp_len);
1105 silc_buffer_put(client_id_list, tmp, tmp_len);
1107 /* Get client mode list */
1108 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1112 client_mode_list = silc_buffer_alloc(tmp_len);
1113 silc_buffer_pull_tail(client_mode_list, tmp_len);
1114 silc_buffer_put(client_mode_list, tmp, tmp_len);
1116 /* Save the users to the channel */
1117 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1118 client_id_list, client_mode_list,
1121 channel->global_users = silc_server_channel_has_global(channel);
1122 channel->users_resolved = TRUE;
1124 silc_buffer_free(client_id_list);
1125 silc_buffer_free(client_mode_list);
1128 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1129 silc_free(channel_id);
1131 silc_server_command_reply_free(cmd);
1134 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1136 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1137 SilcServer server = cmd->server;
1138 SilcStatus status, error;
1139 SilcClientEntry client = NULL;
1140 SilcServerEntry server_entry = NULL;
1141 SilcClientID *client_id = NULL;
1142 SilcServerID *server_id = NULL;
1144 unsigned char *tmp, *pk;
1147 SilcIDPayload idp = NULL;
1149 SilcPublicKey public_key = NULL;
1151 COMMAND_CHECK_STATUS;
1153 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1156 idp = silc_id_payload_parse(tmp, len);
1160 /* Get the public key payload */
1161 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1165 /* Decode the public key */
1167 SILC_GET16_MSB(pk_len, tmp);
1168 SILC_GET16_MSB(type, tmp + 2);
1171 if (type != SILC_SKE_PK_TYPE_SILC)
1174 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1177 id_type = silc_id_payload_get_type(idp);
1178 if (id_type == SILC_ID_CLIENT) {
1179 client_id = silc_id_payload_get_id(idp);
1181 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1184 client = silc_idlist_find_client_by_id(server->global_list,
1185 client_id, TRUE, NULL);
1190 client->data.public_key = public_key;
1192 } else if (id_type == SILC_ID_SERVER) {
1193 server_id = silc_id_payload_get_id(idp);
1195 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1197 if (!server_entry) {
1198 server_entry = silc_idlist_find_server_by_id(server->global_list,
1199 server_id, TRUE, NULL);
1204 server_entry->data.public_key = public_key;
1211 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1213 silc_id_payload_free(idp);
1214 silc_free(client_id);
1215 silc_free(server_id);
1217 silc_pkcs_public_key_free(public_key);
1219 silc_server_command_reply_free(cmd);
1222 SILC_SERVER_CMD_REPLY_FUNC(list)
1224 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1225 SilcServer server = cmd->server;
1226 SilcStatus status, error;
1227 SilcChannelID *channel_id = NULL;
1228 SilcChannelEntry channel;
1229 SilcIDCacheEntry cache;
1231 unsigned char *tmp, *name, *topic;
1232 SilcUInt32 usercount = 0;
1233 bool global_list = FALSE;
1235 COMMAND_CHECK_STATUS;
1237 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1238 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1242 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1243 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1244 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1246 SILC_GET32_MSB(usercount, tmp);
1248 /* Add the channel entry if we do not have it already */
1249 channel = silc_idlist_find_channel_by_name(server->local_list,
1252 channel = silc_idlist_find_channel_by_name(server->global_list,
1257 /* If router did not find such channel in its lists then this must
1258 be bogus channel or some router in the net is buggy. */
1259 if (server->server_type != SILC_SERVER)
1262 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1263 SILC_CHANNEL_MODE_NONE, channel_id,
1264 server->router, NULL, NULL,
1270 /* Found, update expiry */
1271 if (global_list && server->server_type == SILC_SERVER)
1272 cache->expire = time(NULL) + 60;
1275 channel->user_count = usercount;
1278 silc_free(channel->topic);
1279 channel->topic = strdup(topic);
1282 /* Pending callbacks are not executed if this was an list entry */
1283 if (status != SILC_STATUS_OK &&
1284 status != SILC_STATUS_LIST_END) {
1285 silc_server_command_reply_free(cmd);
1289 /* Now purge all old entries from the global list, otherwise we'll might
1290 have non-existent entries for long periods of time in the cache. */
1291 silc_idcache_purge(server->global_list->channels);
1294 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1295 silc_free(channel_id);
1297 silc_server_command_reply_free(cmd);
1300 SILC_SERVER_CMD_REPLY_FUNC(watch)
1302 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1303 SilcStatus status, error;
1305 COMMAND_CHECK_STATUS;
1308 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1310 silc_server_command_reply_free(cmd);