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) {
139 SILC_LOG_ERROR(("Incomplete WHOIS info: %s %s %s",
140 nickname ? nickname : "",
141 username ? username : "",
142 realname ? realname : ""));
146 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
148 SILC_GET32_MSB(mode, tmp);
150 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
154 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
156 /* Check if we have this client cached already. */
158 client = silc_idlist_find_client_by_id(server->local_list, client_id,
161 client = silc_idlist_find_client_by_id(server->global_list, client_id,
167 /* If router did not find such Client ID in its lists then this must
168 be bogus client or some router in the net is buggy. */
169 if (server->server_type != SILC_SERVER)
172 /* Take hostname out of nick string if it includes it. */
173 silc_parse_userfqdn(nickname, &nick, &servername);
175 /* We don't have that client anywhere, add it. The client is added
176 to global list since server didn't have it in the lists so it must be
178 client = silc_idlist_add_client(server->global_list, nick,
180 strdup(realname), client_id,
181 cmd->sock->user_data, NULL,
184 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
188 client->data.status |=
189 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
190 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
192 client->servername = servername;
194 /* We have the client already, update the data */
196 SILC_LOG_DEBUG(("Updating client data"));
198 /* Take hostname out of nick string if it includes it. */
199 silc_parse_userfqdn(nickname, &nick, &servername);
201 /* Remove the old cache entry */
202 silc_idcache_del_by_context(global ? server->global_list->clients :
203 server->local_list->clients, client);
205 silc_free(client->nickname);
206 silc_free(client->username);
207 silc_free(client->userinfo);
208 silc_free(client->servername);
210 client->nickname = nick;
211 client->username = strdup(username);
212 client->userinfo = strdup(realname);
213 client->servername = servername;
215 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
216 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
218 /* If client is global and is not on any channel then add that we'll
219 expire the entry after a while. */
220 if (global && !silc_hash_table_count(client->channels) &&
221 server->server_type == SILC_SERVER)
222 expire = time(NULL) + 300;
224 /* Create new cache entry */
225 silc_idcache_add(global ? server->global_list->clients :
226 server->local_list->clients, nick, client->id,
227 client, expire, NULL);
228 silc_free(client_id);
231 if (fingerprint && flen == sizeof(client->data.fingerprint))
232 memcpy(client->data.fingerprint, fingerprint, flen);
237 /* Reiceved reply for WHOIS command. We sent the whois request to our
238 primary router, if we are normal server, and thus has now received reply
239 to the command. We will figure out what client originally sent us the
240 command and will send the reply to it. If we are router we will figure
241 out who server sent us the command and send reply to that one. */
243 SILC_SERVER_CMD_REPLY_FUNC(whois)
245 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
246 SilcServer server = cmd->server;
247 SilcCommandStatus status, error;
249 COMMAND_CHECK_STATUS;
251 if (!silc_server_command_reply_whois_save(cmd))
254 /* Pending callbacks are not executed if this was an list entry */
255 if (status != SILC_STATUS_OK &&
256 status != SILC_STATUS_LIST_END) {
257 silc_server_command_reply_free(cmd);
262 /* If we received notify for invalid ID we'll remove the ID if we
264 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
265 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
266 SilcClientEntry client;
268 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
270 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
272 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
273 "the entry from cache"));
274 client = silc_idlist_find_client_by_id(server->global_list,
275 client_id, FALSE, NULL);
277 silc_server_remove_from_channels(server, NULL, client, TRUE,
279 silc_idlist_del_client(server->global_list, client);
281 silc_free(client_id);
286 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
287 silc_server_command_reply_free(cmd);
290 /* Caches the received WHOWAS information for a short period of time. */
293 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
295 SilcServer server = cmd->server;
296 SilcUInt32 len, id_len;
297 unsigned char *id_data;
298 char *nickname, *username, *realname, *servername = NULL;
299 SilcClientID *client_id;
300 SilcClientEntry client;
301 SilcIDCacheEntry cache = NULL;
305 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
306 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
307 username = silc_argument_get_arg_type(cmd->args, 4, &len);
308 if (!id_data || !nickname || !username)
311 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
313 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
317 /* Check if we have this client cached already. */
319 client = silc_idlist_find_client_by_id(server->local_list, client_id,
322 client = silc_idlist_find_client_by_id(server->global_list,
323 client_id, FALSE, &cache);
328 /* If router did not find such Client ID in its lists then this must
329 be bogus client or some router in the net is buggy. */
330 if (server->server_type != SILC_SERVER)
333 /* Take hostname out of nick string if it includes it. */
334 silc_parse_userfqdn(nickname, &nick, &servername);
336 /* We don't have that client anywhere, add it. The client is added
337 to global list since server didn't have it in the lists so it must be
339 client = silc_idlist_add_client(server->global_list, nick,
340 strdup(username), strdup(realname),
341 silc_id_dup(client_id, SILC_ID_CLIENT),
342 cmd->sock->user_data, NULL,
343 SILC_ID_CACHE_EXPIRE_DEF);
345 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
349 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
350 client->servername = servername;
352 /* We have the client already, update the data */
354 /* Take hostname out of nick string if it includes it. */
355 silc_parse_userfqdn(nickname, &nick, &servername);
357 silc_free(client->nickname);
358 silc_free(client->username);
360 client->nickname = nick;
361 client->username = strdup(username);
362 client->servername = servername;
364 /* Remove the old cache entry and create a new one */
365 silc_idcache_del_by_context(global ? server->global_list->clients :
366 server->local_list->clients, client);
367 silc_idcache_add(global ? server->global_list->clients :
368 server->local_list->clients, nick, client->id,
372 silc_free(client_id);
377 /* Received reply for WHOWAS command. Cache the client information only for
378 a short period of time. */
380 SILC_SERVER_CMD_REPLY_FUNC(whowas)
382 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
383 SilcCommandStatus status, error;
385 COMMAND_CHECK_STATUS;
387 if (!silc_server_command_reply_whowas_save(cmd))
390 /* Pending callbacks are not executed if this was an list entry */
391 if (status != SILC_STATUS_OK &&
392 status != SILC_STATUS_LIST_END) {
393 silc_server_command_reply_free(cmd);
398 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
399 silc_server_command_reply_free(cmd);
402 /* Caches the received IDENTIFY information. */
405 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
407 SilcServer server = cmd->server;
408 SilcUInt32 len, id_len;
409 unsigned char *id_data;
411 SilcClientID *client_id = NULL;
412 SilcServerID *server_id = NULL;
413 SilcChannelID *channel_id = NULL;
414 SilcClientEntry client;
415 SilcServerEntry server_entry;
416 SilcChannelEntry channel;
419 SilcIDPayload idp = NULL;
423 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
426 idp = silc_id_payload_parse(id_data, id_len);
430 name = silc_argument_get_arg_type(cmd->args, 3, &len);
431 info = silc_argument_get_arg_type(cmd->args, 4, &len);
433 id_type = silc_id_payload_get_type(idp);
437 client_id = silc_id_payload_get_id(idp);
441 SILC_LOG_DEBUG(("Received client information"));
443 client = silc_idlist_find_client_by_id(server->local_list,
444 client_id, FALSE, NULL);
446 client = silc_idlist_find_client_by_id(server->global_list, client_id,
451 /* If router did not find such Client ID in its lists then this must
452 be bogus client or some router in the net is buggy. */
453 if (server->server_type != SILC_SERVER)
458 silc_parse_userfqdn(name, &nick, NULL);
460 /* We don't have that client anywhere, add it. The client is added
461 to global list since server didn't have it in the lists so it must be
463 client = silc_idlist_add_client(server->global_list, nick,
464 info ? strdup(info) : NULL, NULL,
465 client_id, cmd->sock->user_data, NULL,
468 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
471 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
472 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
473 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
475 /* We have the client already, update the data */
477 SILC_LOG_DEBUG(("Updating client data"));
481 silc_parse_userfqdn(name, &nick, NULL);
483 /* Remove the old cache entry */
484 silc_idcache_del_by_context(global ? server->global_list->clients :
485 server->local_list->clients, client);
487 silc_free(client->nickname);
488 client->nickname = nick;
492 silc_free(client->username);
493 client->username = strdup(info);
496 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
497 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
500 /* If client is global and is not on any channel then add that we'll
501 expire the entry after a while. */
502 if (global && !silc_hash_table_count(client->channels) &&
503 server->server_type == SILC_SERVER)
504 expire = time(NULL) + 300;
506 /* Add new cache entry */
507 silc_idcache_add(global ? server->global_list->clients :
508 server->local_list->clients, nick, client->id,
509 client, expire, NULL);
512 silc_free(client_id);
521 server_id = silc_id_payload_get_id(idp);
525 SILC_LOG_DEBUG(("Received server information"));
527 server_entry = silc_idlist_find_server_by_id(server->local_list,
528 server_id, FALSE, NULL);
530 server_entry = silc_idlist_find_server_by_id(server->global_list,
531 server_id, FALSE, NULL);
533 /* If router did not find such Server ID in its lists then this must
534 be bogus server or some router in the net is buggy. */
535 if (server->server_type != SILC_SERVER)
538 /* We don't have that server anywhere, add it. */
539 server_entry = silc_idlist_add_server(server->global_list,
541 server_id, NULL, NULL);
543 silc_free(server_id);
546 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
547 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
548 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
552 silc_free(server_id);
555 case SILC_ID_CHANNEL:
559 channel_id = silc_id_payload_get_id(idp);
563 SILC_LOG_DEBUG(("Received channel information"));
565 channel = silc_idlist_find_channel_by_name(server->local_list,
568 channel = silc_idlist_find_channel_by_name(server->global_list,
571 /* If router did not find such Channel ID in its lists then this must
572 be bogus channel or some router in the net is buggy. */
573 if (server->server_type != SILC_SERVER)
576 /* We don't have that server anywhere, add it. */
577 channel = silc_idlist_add_channel(server->global_list, strdup(name),
578 SILC_CHANNEL_MODE_NONE, channel_id,
579 server->router, NULL, NULL, 0);
581 silc_free(channel_id);
587 silc_free(channel_id);
591 silc_id_payload_free(idp);
595 silc_id_payload_free(idp);
599 /* Received reply for forwarded IDENTIFY command. We have received the
600 requested identify information now and we will cache it. After this we
601 will call the pending command so that the requestee gets the information
604 SILC_SERVER_CMD_REPLY_FUNC(identify)
606 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
607 SilcServer server = cmd->server;
608 SilcCommandStatus status, error;
610 COMMAND_CHECK_STATUS;
612 if (!silc_server_command_reply_identify_save(cmd))
615 /* Pending callbacks are not executed if this was an list entry */
616 if (status != SILC_STATUS_OK &&
617 status != SILC_STATUS_LIST_END) {
618 silc_server_command_reply_free(cmd);
623 /* If we received notify for invalid ID we'll remove the ID if we
625 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
626 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
627 SilcClientEntry client;
629 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
631 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
633 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
634 "the entry from cache"));
635 client = silc_idlist_find_client_by_id(server->global_list,
636 client_id, FALSE, NULL);
638 silc_server_remove_from_channels(server, NULL, client, TRUE,
640 silc_idlist_del_client(server->global_list, client);
642 silc_free(client_id);
647 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
648 silc_server_command_reply_free(cmd);
651 /* Received reply fro INFO command. Cache the server and its information */
653 SILC_SERVER_CMD_REPLY_FUNC(info)
655 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
656 SilcServer server = cmd->server;
657 SilcCommandStatus status, error;
658 SilcServerEntry entry;
659 SilcServerID *server_id;
661 unsigned char *tmp, *name;
663 COMMAND_CHECK_STATUS;
666 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
669 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
674 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
678 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
681 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
684 /* Add the server to global list */
685 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
686 entry = silc_idlist_add_server(server->global_list, name, 0,
687 server_id, NULL, NULL);
689 silc_free(server_id);
692 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
696 /* Get the info string */
697 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
701 entry->server_info = tmp ? strdup(tmp) : NULL;
704 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
705 silc_server_command_reply_free(cmd);
708 /* Received reply fro MOTD command. */
710 SILC_SERVER_CMD_REPLY_FUNC(motd)
712 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
713 SilcServer server = cmd->server;
714 SilcCommandStatus status, error;
715 SilcServerEntry entry = NULL;
716 SilcServerID *server_id;
720 COMMAND_CHECK_STATUS;
723 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
726 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
730 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
733 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
740 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
747 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
748 silc_server_command_reply_free(cmd);
754 /* Received reply for forwarded JOIN command. Router has created or joined
755 the client to the channel. We save some channel information locally
758 SILC_SERVER_CMD_REPLY_FUNC(join)
760 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
761 SilcServer server = cmd->server;
762 SilcIDCacheEntry cache = NULL;
763 SilcCommandStatus status, error;
765 SilcClientID *client_id = NULL;
766 SilcChannelEntry entry;
767 SilcHmac hmac = NULL;
768 SilcUInt32 id_len, len, list_count;
769 unsigned char *id_string;
770 char *channel_name, *tmp;
771 SilcUInt32 mode, created;
772 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
774 COMMAND_CHECK_STATUS;
776 /* Get channel name */
777 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
782 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
787 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
790 client_id = silc_id_payload_parse_id(tmp, len, NULL);
795 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
798 SILC_GET32_MSB(mode, tmp);
800 /* Get created boolean value */
801 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
804 SILC_GET32_MSB(created, tmp);
805 if (created != 0 && created != 1)
808 /* Get channel key */
809 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
811 keyp = silc_buffer_alloc(len);
812 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
813 silc_buffer_put(keyp, tmp, len);
816 /* Parse the Channel ID */
817 id = silc_id_payload_parse_id(id_string, id_len, NULL);
822 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
824 if (!silc_hmac_alloc(tmp, NULL, &hmac))
828 /* Get the list count */
829 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
832 SILC_GET32_MSB(list_count, tmp);
834 /* Get Client ID list */
835 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
839 client_id_list = silc_buffer_alloc(len);
840 silc_buffer_pull_tail(client_id_list, len);
841 silc_buffer_put(client_id_list, tmp, len);
843 /* Get client mode list */
844 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
848 client_mode_list = silc_buffer_alloc(len);
849 silc_buffer_pull_tail(client_mode_list, len);
850 silc_buffer_put(client_mode_list, tmp, len);
852 /* See whether we already have the channel. */
853 entry = silc_idlist_find_channel_by_name(server->local_list,
854 channel_name, &cache);
856 /* Add new channel */
858 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
859 (created == 0 ? "existing" : "created"), channel_name,
860 silc_id_render(id, SILC_ID_CHANNEL)));
862 /* If the channel is found from global list we must move it to the
864 entry = silc_idlist_find_channel_by_name(server->global_list,
865 channel_name, &cache);
867 silc_idlist_del_channel(server->global_list, entry);
869 /* Add the channel to our local list. */
870 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
871 SILC_CHANNEL_MODE_NONE, id,
872 server->router, NULL, hmac, 0);
877 server->stat.my_channels++;
879 /* The entry exists. */
881 /* If ID has changed, then update it to the cache too. */
882 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
883 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
885 entry->disabled = FALSE;
887 /* Remove the founder auth data if the mode is not set but we have
889 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
890 silc_pkcs_public_key_free(entry->founder_key);
891 silc_free(entry->founder_passwd);
892 entry->founder_passwd = NULL;
896 if (entry->hmac_name && hmac) {
897 silc_free(entry->hmac_name);
898 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
901 /* Get the ban list */
902 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
904 silc_free(entry->ban_list);
905 entry->ban_list = silc_memdup(tmp, len);
908 /* Get the invite list */
909 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
911 silc_free(entry->invite_list);
912 entry->invite_list = silc_memdup(tmp, len);
916 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
918 silc_free(entry->topic);
919 entry->topic = strdup(tmp);
922 /* If channel was not created we know there is global users on the
924 entry->global_users = (created == 0 ? TRUE : FALSE);
926 /* If channel was just created the mask must be zero */
927 if (!entry->global_users && mode) {
928 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
929 "new channel, forcing it to zero", cmd->sock->hostname));
933 /* Save channel mode */
936 /* Save channel key */
938 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
939 silc_server_save_channel_key(server, keyp, entry);
940 silc_buffer_free(keyp);
943 /* Save the users to the channel */
944 silc_server_save_users_on_channel(server, cmd->sock, entry,
945 client_id, client_id_list,
946 client_mode_list, list_count);
949 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
950 silc_free(client_id);
951 silc_server_command_reply_free(cmd);
954 silc_buffer_free(client_id_list);
955 if (client_mode_list)
956 silc_buffer_free(client_mode_list);
959 /* Received reply to STATS command. */
961 SILC_SERVER_CMD_REPLY_FUNC(stats)
963 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
964 SilcServer server = cmd->server;
965 SilcCommandStatus status, error;
968 SilcBufferStruct buf;
970 COMMAND_CHECK_STATUS;
972 /* Get statistics structure */
973 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
974 if (server->server_type == SILC_SERVER && tmp) {
975 silc_buffer_set(&buf, tmp, tmp_len);
976 silc_buffer_unformat(&buf,
977 SILC_STR_UI_INT(NULL),
978 SILC_STR_UI_INT(NULL),
979 SILC_STR_UI_INT(NULL),
980 SILC_STR_UI_INT(NULL),
981 SILC_STR_UI_INT(NULL),
982 SILC_STR_UI_INT(NULL),
983 SILC_STR_UI_INT(&server->stat.cell_clients),
984 SILC_STR_UI_INT(&server->stat.cell_channels),
985 SILC_STR_UI_INT(&server->stat.cell_servers),
986 SILC_STR_UI_INT(&server->stat.clients),
987 SILC_STR_UI_INT(&server->stat.channels),
988 SILC_STR_UI_INT(&server->stat.servers),
989 SILC_STR_UI_INT(&server->stat.routers),
990 SILC_STR_UI_INT(&server->stat.server_ops),
991 SILC_STR_UI_INT(&server->stat.router_ops),
996 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
999 SILC_SERVER_CMD_REPLY_FUNC(users)
1001 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1002 SilcServer server = cmd->server;
1003 SilcCommandStatus status, error;
1004 SilcChannelEntry channel;
1005 SilcChannelID *channel_id = NULL;
1006 SilcBuffer client_id_list;
1007 SilcBuffer client_mode_list;
1010 SilcUInt32 list_count;
1012 COMMAND_CHECK_STATUS;
1014 /* Get channel ID */
1015 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1018 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1022 /* Get channel entry */
1023 channel = silc_idlist_find_channel_by_id(server->local_list,
1026 channel = silc_idlist_find_channel_by_id(server->global_list,
1031 if (server->server_type != SILC_SERVER)
1034 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1035 silc_server_send_command(server, server->router->connection,
1036 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1037 1, 5, idp->data, idp->len);
1038 silc_buffer_free(idp);
1040 /* Register pending command callback. After we've received the channel
1041 information we will reprocess this command reply by re-calling this
1042 USERS command reply callback. */
1043 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1045 silc_server_command_reply_users, cmd);
1050 /* Get the list count */
1051 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1054 SILC_GET32_MSB(list_count, tmp);
1056 /* Get Client ID list */
1057 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1061 client_id_list = silc_buffer_alloc(tmp_len);
1062 silc_buffer_pull_tail(client_id_list, tmp_len);
1063 silc_buffer_put(client_id_list, tmp, tmp_len);
1065 /* Get client mode list */
1066 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1070 client_mode_list = silc_buffer_alloc(tmp_len);
1071 silc_buffer_pull_tail(client_mode_list, tmp_len);
1072 silc_buffer_put(client_mode_list, tmp, tmp_len);
1074 /* Save the users to the channel */
1075 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1076 client_id_list, client_mode_list,
1079 silc_buffer_free(client_id_list);
1080 silc_buffer_free(client_mode_list);
1083 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1084 silc_free(channel_id);
1085 silc_server_command_reply_free(cmd);
1088 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1090 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1091 SilcServer server = cmd->server;
1092 SilcCommandStatus status, error;
1093 SilcClientEntry client = NULL;
1094 SilcServerEntry server_entry = NULL;
1095 SilcClientID *client_id = NULL;
1096 SilcServerID *server_id = NULL;
1098 unsigned char *tmp, *pk;
1101 SilcIDPayload idp = NULL;
1103 SilcPublicKey public_key = NULL;
1105 COMMAND_CHECK_STATUS;
1107 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1110 idp = silc_id_payload_parse(tmp, len);
1114 /* Get the public key payload */
1115 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1119 /* Decode the public key */
1121 SILC_GET16_MSB(pk_len, tmp);
1122 SILC_GET16_MSB(type, tmp + 2);
1125 if (type != SILC_SKE_PK_TYPE_SILC)
1128 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1131 id_type = silc_id_payload_get_type(idp);
1132 if (id_type == SILC_ID_CLIENT) {
1133 client_id = silc_id_payload_get_id(idp);
1135 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1138 client = silc_idlist_find_client_by_id(server->global_list,
1139 client_id, TRUE, NULL);
1144 client->data.public_key = public_key;
1145 } else if (id_type == SILC_ID_SERVER) {
1146 server_id = silc_id_payload_get_id(idp);
1148 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1150 if (!server_entry) {
1151 server_entry = silc_idlist_find_server_by_id(server->global_list,
1152 server_id, TRUE, NULL);
1157 server_entry->data.public_key = public_key;
1163 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1165 silc_id_payload_free(idp);
1166 silc_free(client_id);
1167 silc_free(server_id);
1169 silc_pkcs_public_key_free(public_key);
1170 silc_server_command_reply_free(cmd);
1173 SILC_SERVER_CMD_REPLY_FUNC(list)
1175 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1176 SilcServer server = cmd->server;
1177 SilcCommandStatus status, error;
1178 SilcChannelID *channel_id = NULL;
1179 SilcChannelEntry channel;
1180 SilcIDCacheEntry cache;
1182 unsigned char *tmp, *name, *topic;
1183 SilcUInt32 usercount = 0;
1184 bool global_list = FALSE;
1186 COMMAND_CHECK_STATUS;
1188 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1189 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1193 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1194 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1195 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1197 SILC_GET32_MSB(usercount, tmp);
1199 /* Add the channel entry if we do not have it already */
1200 channel = silc_idlist_find_channel_by_name(server->local_list,
1203 channel = silc_idlist_find_channel_by_name(server->global_list,
1208 /* If router did not find such channel in its lists then this must
1209 be bogus channel or some router in the net is buggy. */
1210 if (server->server_type != SILC_SERVER)
1213 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1214 SILC_CHANNEL_MODE_NONE, channel_id,
1215 server->router, NULL, NULL,
1221 /* Found, update expiry */
1222 if (global_list && server->server_type == SILC_SERVER)
1223 cache->expire = time(NULL) + 60;
1226 channel->user_count = usercount;
1229 silc_free(channel->topic);
1230 channel->topic = strdup(topic);
1233 /* Pending callbacks are not executed if this was an list entry */
1234 if (status != SILC_STATUS_OK &&
1235 status != SILC_STATUS_LIST_END) {
1236 silc_server_command_reply_free(cmd);
1240 /* Now purge all old entries from the global list, otherwise we'll might
1241 have non-existent entries for long periods of time in the cache. */
1242 silc_idcache_purge(server->global_list->channels);
1245 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1246 silc_free(channel_id);
1247 silc_server_command_reply_free(cmd);