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
29 #define COMMAND_CHECK_STATUS \
31 SILC_LOG_DEBUG(("Start")); \
32 if (!silc_command_get_status(cmd->payload, &status, &error)) \
36 /* Server command reply list. Not all commands have reply function as
37 they are never sent by server. More maybe added later if need appears. */
38 SilcServerCommandReply silc_command_reply_list[] =
40 SILC_SERVER_CMD_REPLY(whois, WHOIS),
41 SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
42 SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
43 SILC_SERVER_CMD_REPLY(info, INFO),
44 SILC_SERVER_CMD_REPLY(motd, MOTD),
45 SILC_SERVER_CMD_REPLY(join, JOIN),
46 SILC_SERVER_CMD_REPLY(stats, STATS),
47 SILC_SERVER_CMD_REPLY(users, USERS),
48 SILC_SERVER_CMD_REPLY(getkey, GETKEY),
49 SILC_SERVER_CMD_REPLY(list, LIST),
54 /* Process received command reply. */
56 void silc_server_command_reply_process(SilcServer server,
57 SilcSocketConnection sock,
60 SilcServerCommandReply *cmd;
61 SilcServerCommandReplyContext ctx;
62 SilcCommandPayload payload;
66 SILC_LOG_DEBUG(("Start"));
68 /* Get command reply payload from packet */
69 payload = silc_command_payload_parse(buffer->data, buffer->len);
71 /* Silently ignore bad reply packet */
72 SILC_LOG_DEBUG(("Bad command reply packet"));
76 /* Allocate command reply context. This must be free'd by the
77 command reply routine receiving it. */
78 ctx = silc_calloc(1, sizeof(*ctx));
80 ctx->sock = silc_socket_dup(sock);
81 ctx->payload = payload;
82 ctx->args = silc_command_get_args(ctx->payload);
83 ident = silc_command_get_ident(ctx->payload);
85 /* Check for pending commands and mark to be exeucted */
87 silc_server_command_pending_check(server, ctx,
88 silc_command_get(ctx->payload),
89 ident, &ctx->callbacks_count);
91 /* Execute command reply */
92 command = silc_command_get(ctx->payload);
93 for (cmd = silc_command_reply_list; cmd->cb; cmd++)
94 if (cmd->cmd == command)
97 if (cmd == NULL || !cmd->cb) {
98 silc_server_command_reply_free(ctx);
105 /* Free command reply context and its internals. */
107 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
110 silc_command_payload_free(cmd->payload);
112 silc_socket_free(cmd->sock); /* Decrease the reference counter */
113 silc_free(cmd->callbacks);
118 /* Caches the received WHOIS information. */
121 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
123 SilcServer server = cmd->server;
124 unsigned char *tmp, *id_data;
125 char *nickname, *username, *realname, *servername = NULL;
126 unsigned char *fingerprint;
127 SilcClientID *client_id;
128 SilcClientEntry client;
131 SilcUInt32 mode = 0, len, id_len, flen;
134 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
135 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
136 username = silc_argument_get_arg_type(cmd->args, 4, &len);
137 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
138 if (!id_data || !nickname || !username || !realname)
141 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
143 SILC_GET32_MSB(mode, tmp);
145 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
149 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
151 /* Check if we have this client cached already. */
153 client = silc_idlist_find_client_by_id(server->local_list, client_id,
156 client = silc_idlist_find_client_by_id(server->global_list, client_id,
162 /* If router did not find such Client ID in its lists then this must
163 be bogus client or some router in the net is buggy. */
164 if (server->server_type != SILC_SERVER)
167 /* Take hostname out of nick string if it includes it. */
168 silc_parse_userfqdn(nickname, &nick, &servername);
170 /* We don't have that client anywhere, add it. The client is added
171 to global list since server didn't have it in the lists so it must be
173 client = silc_idlist_add_client(server->global_list, nick,
175 strdup(realname), client_id,
176 cmd->sock->user_data, NULL,
179 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
183 client->data.status |=
184 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
185 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
187 client->servername = servername;
189 /* We have the client already, update the data */
191 SILC_LOG_DEBUG(("Updating client data"));
193 /* Take hostname out of nick string if it includes it. */
194 silc_parse_userfqdn(nickname, &nick, &servername);
196 /* Remove the old cache entry */
197 silc_idcache_del_by_context(global ? server->global_list->clients :
198 server->local_list->clients, client);
200 silc_free(client->nickname);
201 silc_free(client->username);
202 silc_free(client->userinfo);
203 silc_free(client->servername);
205 client->nickname = nick;
206 client->username = strdup(username);
207 client->userinfo = strdup(realname);
208 client->servername = servername;
210 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
211 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
213 /* If client is global and is not on any channel then add that we'll
214 expire the entry after a while. */
215 if (global && !silc_hash_table_count(client->channels) &&
216 server->server_type == SILC_SERVER)
217 expire = time(NULL) + 300;
219 /* Create new cache entry */
220 silc_idcache_add(global ? server->global_list->clients :
221 server->local_list->clients, nick, client->id,
222 client, expire, NULL);
223 silc_free(client_id);
226 if (fingerprint && flen == sizeof(client->data.fingerprint))
227 memcpy(client->data.fingerprint, fingerprint, flen);
232 /* Reiceved reply for WHOIS command. We sent the whois request to our
233 primary router, if we are normal server, and thus has now received reply
234 to the command. We will figure out what client originally sent us the
235 command and will send the reply to it. If we are router we will figure
236 out who server sent us the command and send reply to that one. */
238 SILC_SERVER_CMD_REPLY_FUNC(whois)
240 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
241 SilcServer server = cmd->server;
242 SilcCommandStatus status, error;
244 COMMAND_CHECK_STATUS;
246 if (!silc_server_command_reply_whois_save(cmd))
249 /* Pending callbacks are not executed if this was an list entry */
250 if (status != SILC_STATUS_OK &&
251 status != SILC_STATUS_LIST_END) {
252 silc_server_command_reply_free(cmd);
257 /* If we received notify for invalid ID we'll remove the ID if we
259 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
260 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
261 SilcClientEntry client;
263 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
265 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
267 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
268 "the entry from cache"));
269 client = silc_idlist_find_client_by_id(server->global_list,
270 client_id, FALSE, NULL);
272 silc_server_remove_from_channels(server, NULL, client, TRUE,
274 silc_idlist_del_client(server->global_list, client);
276 silc_free(client_id);
281 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
282 silc_server_command_reply_free(cmd);
285 /* Caches the received WHOWAS information for a short period of time. */
288 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
290 SilcServer server = cmd->server;
291 SilcUInt32 len, id_len;
292 unsigned char *id_data;
293 char *nickname, *username, *realname, *servername = NULL;
294 SilcClientID *client_id;
295 SilcClientEntry client;
296 SilcIDCacheEntry cache = NULL;
300 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
301 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
302 username = silc_argument_get_arg_type(cmd->args, 4, &len);
303 if (!id_data || !nickname || !username)
306 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
308 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
312 /* Check if we have this client cached already. */
314 client = silc_idlist_find_client_by_id(server->local_list, client_id,
317 client = silc_idlist_find_client_by_id(server->global_list,
318 client_id, FALSE, &cache);
323 /* If router did not find such Client ID in its lists then this must
324 be bogus client or some router in the net is buggy. */
325 if (server->server_type != SILC_SERVER)
328 /* Take hostname out of nick string if it includes it. */
329 silc_parse_userfqdn(nickname, &nick, &servername);
331 /* We don't have that client anywhere, add it. The client is added
332 to global list since server didn't have it in the lists so it must be
334 client = silc_idlist_add_client(server->global_list, nick,
335 strdup(username), strdup(realname),
336 silc_id_dup(client_id, SILC_ID_CLIENT),
337 cmd->sock->user_data, NULL,
338 SILC_ID_CACHE_EXPIRE_DEF);
340 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
344 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
345 client->servername = servername;
347 /* We have the client already, update the data */
349 /* Take hostname out of nick string if it includes it. */
350 silc_parse_userfqdn(nickname, &nick, &servername);
352 silc_free(client->nickname);
353 silc_free(client->username);
355 client->nickname = nick;
356 client->username = strdup(username);
357 client->servername = servername;
359 /* Remove the old cache entry and create a new one */
360 silc_idcache_del_by_context(global ? server->global_list->clients :
361 server->local_list->clients, client);
362 silc_idcache_add(global ? server->global_list->clients :
363 server->local_list->clients, nick, client->id,
367 silc_free(client_id);
372 /* Received reply for WHOWAS command. Cache the client information only for
373 a short period of time. */
375 SILC_SERVER_CMD_REPLY_FUNC(whowas)
377 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
378 SilcCommandStatus status, error;
380 COMMAND_CHECK_STATUS;
382 if (!silc_server_command_reply_whowas_save(cmd))
385 /* Pending callbacks are not executed if this was an list entry */
386 if (status != SILC_STATUS_OK &&
387 status != SILC_STATUS_LIST_END) {
388 silc_server_command_reply_free(cmd);
393 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
394 silc_server_command_reply_free(cmd);
397 /* Caches the received IDENTIFY information. */
400 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
402 SilcServer server = cmd->server;
403 SilcUInt32 len, id_len;
404 unsigned char *id_data;
406 SilcClientID *client_id = NULL;
407 SilcServerID *server_id = NULL;
408 SilcChannelID *channel_id = NULL;
409 SilcClientEntry client;
410 SilcServerEntry server_entry;
411 SilcChannelEntry channel;
414 SilcIDPayload idp = NULL;
418 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
421 idp = silc_id_payload_parse(id_data, id_len);
425 name = silc_argument_get_arg_type(cmd->args, 3, &len);
426 info = silc_argument_get_arg_type(cmd->args, 4, &len);
428 id_type = silc_id_payload_get_type(idp);
432 client_id = silc_id_payload_get_id(idp);
436 SILC_LOG_DEBUG(("Received client information"));
438 client = silc_idlist_find_client_by_id(server->local_list,
439 client_id, FALSE, NULL);
441 client = silc_idlist_find_client_by_id(server->global_list, client_id,
446 /* If router did not find such Client ID in its lists then this must
447 be bogus client or some router in the net is buggy. */
448 if (server->server_type != SILC_SERVER)
453 silc_parse_userfqdn(name, &nick, NULL);
455 /* We don't have that client anywhere, add it. The client is added
456 to global list since server didn't have it in the lists so it must be
458 client = silc_idlist_add_client(server->global_list, nick,
459 info ? strdup(info) : NULL, NULL,
460 client_id, cmd->sock->user_data, NULL,
463 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
466 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
467 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
468 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
470 /* We have the client already, update the data */
472 SILC_LOG_DEBUG(("Updating client data"));
476 silc_parse_userfqdn(name, &nick, NULL);
478 /* Remove the old cache entry */
479 silc_idcache_del_by_context(global ? server->global_list->clients :
480 server->local_list->clients, client);
482 silc_free(client->nickname);
483 client->nickname = nick;
487 silc_free(client->username);
488 client->username = strdup(info);
491 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
492 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
495 /* If client is global and is not on any channel then add that we'll
496 expire the entry after a while. */
497 if (global && !silc_hash_table_count(client->channels) &&
498 server->server_type == SILC_SERVER)
499 expire = time(NULL) + 300;
501 /* Add new cache entry */
502 silc_idcache_add(global ? server->global_list->clients :
503 server->local_list->clients, nick, client->id,
504 client, expire, NULL);
507 silc_free(client_id);
516 server_id = silc_id_payload_get_id(idp);
520 SILC_LOG_DEBUG(("Received server information"));
522 server_entry = silc_idlist_find_server_by_id(server->local_list,
523 server_id, FALSE, NULL);
525 server_entry = silc_idlist_find_server_by_id(server->global_list,
526 server_id, FALSE, NULL);
528 /* If router did not find such Server ID in its lists then this must
529 be bogus server or some router in the net is buggy. */
530 if (server->server_type != SILC_SERVER)
533 /* We don't have that server anywhere, add it. */
534 server_entry = silc_idlist_add_server(server->global_list,
536 server_id, NULL, NULL);
538 silc_free(server_id);
541 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
542 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
543 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
547 silc_free(server_id);
550 case SILC_ID_CHANNEL:
554 channel_id = silc_id_payload_get_id(idp);
558 SILC_LOG_DEBUG(("Received channel information"));
560 channel = silc_idlist_find_channel_by_name(server->local_list,
563 channel = silc_idlist_find_channel_by_name(server->global_list,
566 /* If router did not find such Channel ID in its lists then this must
567 be bogus channel or some router in the net is buggy. */
568 if (server->server_type != SILC_SERVER)
571 /* We don't have that server anywhere, add it. */
572 channel = silc_idlist_add_channel(server->global_list, strdup(name),
573 SILC_CHANNEL_MODE_NONE, channel_id,
574 server->router, NULL, NULL, 0);
576 silc_free(channel_id);
582 silc_free(channel_id);
586 silc_id_payload_free(idp);
590 silc_id_payload_free(idp);
594 /* Received reply for forwarded IDENTIFY command. We have received the
595 requested identify information now and we will cache it. After this we
596 will call the pending command so that the requestee gets the information
599 SILC_SERVER_CMD_REPLY_FUNC(identify)
601 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
602 SilcServer server = cmd->server;
603 SilcCommandStatus status, error;
605 COMMAND_CHECK_STATUS;
607 if (!silc_server_command_reply_identify_save(cmd))
610 /* Pending callbacks are not executed if this was an list entry */
611 if (status != SILC_STATUS_OK &&
612 status != SILC_STATUS_LIST_END) {
613 silc_server_command_reply_free(cmd);
618 /* If we received notify for invalid ID we'll remove the ID if we
620 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
621 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
622 SilcClientEntry client;
624 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
626 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
628 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
629 "the entry from cache"));
630 client = silc_idlist_find_client_by_id(server->global_list,
631 client_id, FALSE, NULL);
633 silc_server_remove_from_channels(server, NULL, client, TRUE,
635 silc_idlist_del_client(server->global_list, client);
637 silc_free(client_id);
642 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
643 silc_server_command_reply_free(cmd);
646 /* Received reply fro INFO command. Cache the server and its information */
648 SILC_SERVER_CMD_REPLY_FUNC(info)
650 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
651 SilcServer server = cmd->server;
652 SilcCommandStatus status, error;
653 SilcServerEntry entry;
654 SilcServerID *server_id;
656 unsigned char *tmp, *name;
658 COMMAND_CHECK_STATUS;
661 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
664 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
669 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
673 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
676 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
679 /* Add the server to global list */
680 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
681 entry = silc_idlist_add_server(server->global_list, name, 0,
682 server_id, NULL, NULL);
684 silc_free(server_id);
687 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
691 /* Get the info string */
692 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
696 entry->server_info = tmp ? strdup(tmp) : NULL;
699 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
700 silc_server_command_reply_free(cmd);
703 /* Received reply fro MOTD command. */
705 SILC_SERVER_CMD_REPLY_FUNC(motd)
707 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
708 SilcServer server = cmd->server;
709 SilcCommandStatus status, error;
710 SilcServerEntry entry = NULL;
711 SilcServerID *server_id;
715 COMMAND_CHECK_STATUS;
718 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
721 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
725 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
728 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
735 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
742 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
743 silc_server_command_reply_free(cmd);
749 /* Received reply for forwarded JOIN command. Router has created or joined
750 the client to the channel. We save some channel information locally
753 SILC_SERVER_CMD_REPLY_FUNC(join)
755 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
756 SilcServer server = cmd->server;
757 SilcIDCacheEntry cache = NULL;
758 SilcCommandStatus status, error;
760 SilcClientID *client_id = NULL;
761 SilcChannelEntry entry;
762 SilcHmac hmac = NULL;
763 SilcUInt32 id_len, len, list_count;
764 unsigned char *id_string;
765 char *channel_name, *tmp;
766 SilcUInt32 mode, created;
767 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
769 COMMAND_CHECK_STATUS;
771 /* Get channel name */
772 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
777 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
782 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
785 client_id = silc_id_payload_parse_id(tmp, len, NULL);
790 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
793 SILC_GET32_MSB(mode, tmp);
795 /* Get created boolean value */
796 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
799 SILC_GET32_MSB(created, tmp);
800 if (created != 0 && created != 1)
803 /* Get channel key */
804 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
806 keyp = silc_buffer_alloc(len);
807 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
808 silc_buffer_put(keyp, tmp, len);
811 /* Parse the Channel ID */
812 id = silc_id_payload_parse_id(id_string, id_len, NULL);
817 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
819 if (!silc_hmac_alloc(tmp, NULL, &hmac))
823 /* Get the list count */
824 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
827 SILC_GET32_MSB(list_count, tmp);
829 /* Get Client ID list */
830 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
834 client_id_list = silc_buffer_alloc(len);
835 silc_buffer_pull_tail(client_id_list, len);
836 silc_buffer_put(client_id_list, tmp, len);
838 /* Get client mode list */
839 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
843 client_mode_list = silc_buffer_alloc(len);
844 silc_buffer_pull_tail(client_mode_list, len);
845 silc_buffer_put(client_mode_list, tmp, len);
847 /* See whether we already have the channel. */
848 entry = silc_idlist_find_channel_by_name(server->local_list,
849 channel_name, &cache);
851 /* Add new channel */
853 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
854 (created == 0 ? "existing" : "created"), channel_name,
855 silc_id_render(id, SILC_ID_CHANNEL)));
857 /* If the channel is found from global list we must move it to the
859 entry = silc_idlist_find_channel_by_name(server->global_list,
860 channel_name, &cache);
862 silc_idlist_del_channel(server->global_list, entry);
864 /* Add the channel to our local list. */
865 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
866 SILC_CHANNEL_MODE_NONE, id,
867 server->router, NULL, hmac, 0);
872 server->stat.my_channels++;
874 /* The entry exists. */
876 /* If ID has changed, then update it to the cache too. */
877 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
878 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
880 entry->disabled = FALSE;
882 /* Remove the founder auth data if the mode is not set but we have
884 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
885 silc_pkcs_public_key_free(entry->founder_key);
886 silc_free(entry->founder_passwd);
887 entry->founder_passwd = NULL;
891 if (entry->hmac_name && hmac) {
892 silc_free(entry->hmac_name);
893 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
896 /* Get the ban list */
897 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
899 silc_free(entry->ban_list);
900 entry->ban_list = silc_memdup(tmp, len);
903 /* Get the invite list */
904 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
906 silc_free(entry->invite_list);
907 entry->invite_list = silc_memdup(tmp, len);
911 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
913 silc_free(entry->topic);
914 entry->topic = strdup(tmp);
917 /* If channel was not created we know there is global users on the
919 entry->global_users = (created == 0 ? TRUE : FALSE);
921 /* If channel was just created the mask must be zero */
922 if (!entry->global_users && mode) {
923 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
924 "new channel, forcing it to zero", cmd->sock->hostname));
928 /* Save channel mode */
931 /* Save channel key */
933 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
934 silc_server_save_channel_key(server, keyp, entry);
935 silc_buffer_free(keyp);
938 /* Save the users to the channel */
939 silc_server_save_users_on_channel(server, cmd->sock, entry,
940 client_id, client_id_list,
941 client_mode_list, list_count);
944 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
945 silc_free(client_id);
946 silc_server_command_reply_free(cmd);
949 silc_buffer_free(client_id_list);
950 if (client_mode_list)
951 silc_buffer_free(client_mode_list);
954 /* Received reply to STATS command. */
956 SILC_SERVER_CMD_REPLY_FUNC(stats)
958 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
959 SilcServer server = cmd->server;
960 SilcCommandStatus status, error;
963 SilcBufferStruct buf;
965 COMMAND_CHECK_STATUS;
967 /* Get statistics structure */
968 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
969 if (server->server_type == SILC_SERVER && tmp) {
970 silc_buffer_set(&buf, tmp, tmp_len);
971 silc_buffer_unformat(&buf,
972 SILC_STR_UI_INT(NULL),
973 SILC_STR_UI_INT(NULL),
974 SILC_STR_UI_INT(NULL),
975 SILC_STR_UI_INT(NULL),
976 SILC_STR_UI_INT(NULL),
977 SILC_STR_UI_INT(NULL),
978 SILC_STR_UI_INT(&server->stat.cell_clients),
979 SILC_STR_UI_INT(&server->stat.cell_channels),
980 SILC_STR_UI_INT(&server->stat.cell_servers),
981 SILC_STR_UI_INT(&server->stat.clients),
982 SILC_STR_UI_INT(&server->stat.channels),
983 SILC_STR_UI_INT(&server->stat.servers),
984 SILC_STR_UI_INT(&server->stat.routers),
985 SILC_STR_UI_INT(&server->stat.server_ops),
986 SILC_STR_UI_INT(&server->stat.router_ops),
991 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
994 SILC_SERVER_CMD_REPLY_FUNC(users)
996 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
997 SilcServer server = cmd->server;
998 SilcCommandStatus status, error;
999 SilcChannelEntry channel;
1000 SilcChannelID *channel_id = NULL;
1001 SilcBuffer client_id_list;
1002 SilcBuffer client_mode_list;
1005 SilcUInt32 list_count;
1007 COMMAND_CHECK_STATUS;
1009 /* Get channel ID */
1010 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1013 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1017 /* Get channel entry */
1018 channel = silc_idlist_find_channel_by_id(server->local_list,
1021 channel = silc_idlist_find_channel_by_id(server->global_list,
1026 if (server->server_type != SILC_SERVER)
1029 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1030 silc_server_send_command(server, server->router->connection,
1031 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1032 1, 5, idp->data, idp->len);
1033 silc_buffer_free(idp);
1035 /* Register pending command callback. After we've received the channel
1036 information we will reprocess this command reply by re-calling this
1037 USERS command reply callback. */
1038 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1040 silc_server_command_reply_users, cmd);
1045 /* Get the list count */
1046 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1049 SILC_GET32_MSB(list_count, tmp);
1051 /* Get Client ID list */
1052 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1056 client_id_list = silc_buffer_alloc(tmp_len);
1057 silc_buffer_pull_tail(client_id_list, tmp_len);
1058 silc_buffer_put(client_id_list, tmp, tmp_len);
1060 /* Get client mode list */
1061 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1065 client_mode_list = silc_buffer_alloc(tmp_len);
1066 silc_buffer_pull_tail(client_mode_list, tmp_len);
1067 silc_buffer_put(client_mode_list, tmp, tmp_len);
1069 /* Save the users to the channel */
1070 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1071 client_id_list, client_mode_list,
1074 silc_buffer_free(client_id_list);
1075 silc_buffer_free(client_mode_list);
1078 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1079 silc_free(channel_id);
1080 silc_server_command_reply_free(cmd);
1083 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1085 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1086 SilcServer server = cmd->server;
1087 SilcCommandStatus status, error;
1088 SilcClientEntry client = NULL;
1089 SilcServerEntry server_entry = NULL;
1090 SilcClientID *client_id = NULL;
1091 SilcServerID *server_id = NULL;
1093 unsigned char *tmp, *pk;
1096 SilcIDPayload idp = NULL;
1098 SilcPublicKey public_key = NULL;
1100 COMMAND_CHECK_STATUS;
1102 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1105 idp = silc_id_payload_parse(tmp, len);
1109 /* Get the public key payload */
1110 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1114 /* Decode the public key */
1116 SILC_GET16_MSB(pk_len, tmp);
1117 SILC_GET16_MSB(type, tmp + 2);
1120 if (type != SILC_SKE_PK_TYPE_SILC)
1123 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1126 id_type = silc_id_payload_get_type(idp);
1127 if (id_type == SILC_ID_CLIENT) {
1128 client_id = silc_id_payload_get_id(idp);
1130 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1133 client = silc_idlist_find_client_by_id(server->global_list,
1134 client_id, TRUE, NULL);
1139 client->data.public_key = public_key;
1140 } else if (id_type == SILC_ID_SERVER) {
1141 server_id = silc_id_payload_get_id(idp);
1143 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1145 if (!server_entry) {
1146 server_entry = silc_idlist_find_server_by_id(server->global_list,
1147 server_id, TRUE, NULL);
1152 server_entry->data.public_key = public_key;
1158 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1160 silc_id_payload_free(idp);
1161 silc_free(client_id);
1162 silc_free(server_id);
1164 silc_pkcs_public_key_free(public_key);
1165 silc_server_command_reply_free(cmd);
1168 SILC_SERVER_CMD_REPLY_FUNC(list)
1170 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1171 SilcServer server = cmd->server;
1172 SilcCommandStatus status, error;
1173 SilcChannelID *channel_id = NULL;
1174 SilcChannelEntry channel;
1175 SilcIDCacheEntry cache;
1177 unsigned char *tmp, *name, *topic;
1178 SilcUInt32 usercount = 0;
1179 bool global_list = FALSE;
1181 COMMAND_CHECK_STATUS;
1183 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1184 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1188 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1189 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1190 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1192 SILC_GET32_MSB(usercount, tmp);
1194 /* Add the channel entry if we do not have it already */
1195 channel = silc_idlist_find_channel_by_name(server->local_list,
1198 channel = silc_idlist_find_channel_by_name(server->global_list,
1203 /* If router did not find such channel in its lists then this must
1204 be bogus channel or some router in the net is buggy. */
1205 if (server->server_type != SILC_SERVER)
1208 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1209 SILC_CHANNEL_MODE_NONE, channel_id,
1210 server->router, NULL, NULL,
1216 /* Found, update expiry */
1217 if (global_list && server->server_type == SILC_SERVER)
1218 cache->expire = time(NULL) + 60;
1221 channel->user_count = usercount;
1224 silc_free(channel->topic);
1225 channel->topic = strdup(topic);
1228 /* Pending callbacks are not executed if this was an list entry */
1229 if (status != SILC_STATUS_OK &&
1230 status != SILC_STATUS_LIST_END) {
1231 silc_server_command_reply_free(cmd);
1235 /* Now purge all old entries from the global list, otherwise we'll might
1236 have non-existent entries for long periods of time in the cache. */
1237 silc_idcache_purge(server->global_list->channels);
1240 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1241 silc_free(channel_id);
1242 silc_server_command_reply_free(cmd);