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, *umodes;
125 char *nickname, *username, *realname, *servername = NULL;
126 unsigned char *fingerprint;
127 SilcClientID *client_id;
128 SilcClientEntry client;
129 SilcIDCacheEntry cache = NULL;
132 SilcUInt32 mode = 0, len, len2, 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 /* Create new cache entry */
214 silc_idcache_add(global ? server->global_list->clients :
215 server->local_list->clients, nick, client->id,
217 silc_free(client_id);
220 /* Save channel list if it was sent to us */
221 if (server->server_type == SILC_SERVER) {
222 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
223 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
225 SilcBufferStruct channels_buf, umodes_buf;
226 silc_buffer_set(&channels_buf, tmp, len);
227 silc_buffer_set(&umodes_buf, umodes, len2);
228 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
231 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
235 /* If client is global and is not on any channel then add that we'll
236 expire the entry after a while. */
237 if (global && !silc_hash_table_count(client->channels))
238 cache->expire = time(NULL) + 300;
241 if (fingerprint && flen == sizeof(client->data.fingerprint))
242 memcpy(client->data.fingerprint, fingerprint, flen);
247 /* Reiceved reply for WHOIS command. We sent the whois request to our
248 primary router, if we are normal server, and thus has now received reply
249 to the command. We will figure out what client originally sent us the
250 command and will send the reply to it. If we are router we will figure
251 out who server sent us the command and send reply to that one. */
253 SILC_SERVER_CMD_REPLY_FUNC(whois)
255 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
256 SilcServer server = cmd->server;
257 SilcStatus status, error;
259 COMMAND_CHECK_STATUS;
261 if (!silc_server_command_reply_whois_save(cmd))
264 /* Pending callbacks are not executed if this was an list entry */
265 if (status != SILC_STATUS_OK &&
266 status != SILC_STATUS_LIST_END) {
267 silc_server_command_reply_free(cmd);
272 /* If we received notify for invalid ID we'll remove the ID if we
274 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
275 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
276 SilcClientEntry client;
278 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
280 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
282 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
283 "the entry from cache"));
284 client = silc_idlist_find_client_by_id(server->global_list,
285 client_id, FALSE, NULL);
287 silc_server_remove_from_channels(server, NULL, client, TRUE,
289 silc_idlist_del_client(server->global_list, client);
291 silc_free(client_id);
296 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
297 silc_server_command_reply_free(cmd);
300 /* Caches the received WHOWAS information for a short period of time. */
303 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
305 SilcServer server = cmd->server;
306 SilcUInt32 len, id_len;
307 unsigned char *id_data;
308 char *nickname, *username, *realname, *servername = NULL;
309 SilcClientID *client_id;
310 SilcClientEntry client;
311 SilcIDCacheEntry cache = NULL;
315 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
316 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
317 username = silc_argument_get_arg_type(cmd->args, 4, &len);
318 if (!id_data || !nickname || !username)
321 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
323 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
327 /* Check if we have this client cached already. */
329 client = silc_idlist_find_client_by_id(server->local_list, client_id,
332 client = silc_idlist_find_client_by_id(server->global_list,
333 client_id, FALSE, &cache);
338 /* If router did not find such Client ID in its lists then this must
339 be bogus client or some router in the net is buggy. */
340 if (server->server_type != SILC_SERVER)
343 /* Take hostname out of nick string if it includes it. */
344 silc_parse_userfqdn(nickname, &nick, &servername);
346 /* We don't have that client anywhere, add it. The client is added
347 to global list since server didn't have it in the lists so it must be
349 client = silc_idlist_add_client(server->global_list, nick,
350 strdup(username), strdup(realname),
351 silc_id_dup(client_id, SILC_ID_CLIENT),
352 cmd->sock->user_data, NULL,
353 SILC_ID_CACHE_EXPIRE_DEF);
355 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
359 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
360 client->servername = servername;
362 /* We have the client already, update the data */
364 /* Take hostname out of nick string if it includes it. */
365 silc_parse_userfqdn(nickname, &nick, &servername);
367 silc_free(client->nickname);
368 silc_free(client->username);
370 client->nickname = nick;
371 client->username = strdup(username);
372 client->servername = servername;
374 /* Remove the old cache entry and create a new one */
375 silc_idcache_del_by_context(global ? server->global_list->clients :
376 server->local_list->clients, client);
377 silc_idcache_add(global ? server->global_list->clients :
378 server->local_list->clients, nick, client->id,
382 silc_free(client_id);
387 /* Received reply for WHOWAS command. Cache the client information only for
388 a short period of time. */
390 SILC_SERVER_CMD_REPLY_FUNC(whowas)
392 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
393 SilcStatus status, error;
395 COMMAND_CHECK_STATUS;
397 if (!silc_server_command_reply_whowas_save(cmd))
400 /* Pending callbacks are not executed if this was an list entry */
401 if (status != SILC_STATUS_OK &&
402 status != SILC_STATUS_LIST_END) {
403 silc_server_command_reply_free(cmd);
408 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
409 silc_server_command_reply_free(cmd);
412 /* Caches the received IDENTIFY information. */
415 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
417 SilcServer server = cmd->server;
418 SilcUInt32 len, id_len;
419 unsigned char *id_data;
421 SilcClientID *client_id = NULL;
422 SilcServerID *server_id = NULL;
423 SilcChannelID *channel_id = NULL;
424 SilcClientEntry client;
425 SilcServerEntry server_entry;
426 SilcChannelEntry channel;
429 SilcIDPayload idp = NULL;
433 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
436 idp = silc_id_payload_parse(id_data, id_len);
440 name = silc_argument_get_arg_type(cmd->args, 3, &len);
441 info = silc_argument_get_arg_type(cmd->args, 4, &len);
443 id_type = silc_id_payload_get_type(idp);
447 client_id = silc_id_payload_get_id(idp);
451 SILC_LOG_DEBUG(("Received client information"));
453 client = silc_idlist_find_client_by_id(server->local_list,
454 client_id, FALSE, NULL);
456 client = silc_idlist_find_client_by_id(server->global_list, client_id,
461 /* If router did not find such Client ID in its lists then this must
462 be bogus client or some router in the net is buggy. */
463 if (server->server_type != SILC_SERVER)
468 silc_parse_userfqdn(name, &nick, NULL);
470 /* We don't have that client anywhere, add it. The client is added
471 to global list since server didn't have it in the lists so it must be
473 client = silc_idlist_add_client(server->global_list, nick,
474 info ? strdup(info) : NULL, NULL,
475 client_id, cmd->sock->user_data, NULL,
478 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
481 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
482 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
483 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
485 /* We have the client already, update the data */
487 SILC_LOG_DEBUG(("Updating client data"));
491 silc_parse_userfqdn(name, &nick, NULL);
493 /* Remove the old cache entry */
494 silc_idcache_del_by_context(global ? server->global_list->clients :
495 server->local_list->clients, client);
497 silc_free(client->nickname);
498 client->nickname = nick;
502 silc_free(client->username);
503 client->username = strdup(info);
506 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
507 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
510 /* If client is global and is not on any channel then add that we'll
511 expire the entry after a while. */
512 if (global && !silc_hash_table_count(client->channels) &&
513 server->server_type == SILC_SERVER)
514 expire = time(NULL) + 300;
516 /* Add new cache entry */
517 silc_idcache_add(global ? server->global_list->clients :
518 server->local_list->clients, nick, client->id,
519 client, expire, NULL);
522 silc_free(client_id);
531 server_id = silc_id_payload_get_id(idp);
535 SILC_LOG_DEBUG(("Received server information"));
537 server_entry = silc_idlist_find_server_by_id(server->local_list,
538 server_id, FALSE, NULL);
540 server_entry = silc_idlist_find_server_by_id(server->global_list,
541 server_id, FALSE, NULL);
543 /* If router did not find such Server ID in its lists then this must
544 be bogus server or some router in the net is buggy. */
545 if (server->server_type != SILC_SERVER)
548 /* We don't have that server anywhere, add it. */
549 server_entry = silc_idlist_add_server(server->global_list,
551 server_id, NULL, NULL);
553 silc_free(server_id);
556 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
557 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
558 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
562 silc_free(server_id);
565 case SILC_ID_CHANNEL:
569 channel_id = silc_id_payload_get_id(idp);
573 SILC_LOG_DEBUG(("Received channel information"));
575 channel = silc_idlist_find_channel_by_name(server->local_list,
578 channel = silc_idlist_find_channel_by_name(server->global_list,
581 /* If router did not find such Channel ID in its lists then this must
582 be bogus channel or some router in the net is buggy. */
583 if (server->server_type != SILC_SERVER)
586 /* We don't have that server anywhere, add it. */
587 channel = silc_idlist_add_channel(server->global_list, strdup(name),
588 SILC_CHANNEL_MODE_NONE, channel_id,
589 server->router, NULL, NULL, 0);
591 silc_free(channel_id);
597 silc_free(channel_id);
601 silc_id_payload_free(idp);
605 silc_id_payload_free(idp);
609 /* Received reply for forwarded IDENTIFY command. We have received the
610 requested identify information now and we will cache it. After this we
611 will call the pending command so that the requestee gets the information
614 SILC_SERVER_CMD_REPLY_FUNC(identify)
616 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
617 SilcServer server = cmd->server;
618 SilcStatus status, error;
620 COMMAND_CHECK_STATUS;
622 if (!silc_server_command_reply_identify_save(cmd))
625 /* Pending callbacks are not executed if this was an list entry */
626 if (status != SILC_STATUS_OK &&
627 status != SILC_STATUS_LIST_END) {
628 silc_server_command_reply_free(cmd);
633 /* If we received notify for invalid ID we'll remove the ID if we
635 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
636 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
637 SilcClientEntry client;
639 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
641 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
643 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
644 "the entry from cache"));
645 client = silc_idlist_find_client_by_id(server->global_list,
646 client_id, FALSE, NULL);
648 silc_server_remove_from_channels(server, NULL, client, TRUE,
650 silc_idlist_del_client(server->global_list, client);
652 silc_free(client_id);
657 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
658 silc_server_command_reply_free(cmd);
661 /* Received reply fro INFO command. Cache the server and its information */
663 SILC_SERVER_CMD_REPLY_FUNC(info)
665 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
666 SilcServer server = cmd->server;
667 SilcStatus status, error;
668 SilcServerEntry entry;
669 SilcServerID *server_id;
671 unsigned char *tmp, *name;
673 COMMAND_CHECK_STATUS;
676 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
679 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
684 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
688 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
691 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
694 /* Add the server to global list */
695 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
696 entry = silc_idlist_add_server(server->global_list, name, 0,
697 server_id, NULL, NULL);
699 silc_free(server_id);
702 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
706 /* Get the info string */
707 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
711 entry->server_info = tmp ? strdup(tmp) : NULL;
714 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
715 silc_server_command_reply_free(cmd);
718 /* Received reply fro MOTD command. */
720 SILC_SERVER_CMD_REPLY_FUNC(motd)
722 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
723 SilcServer server = cmd->server;
724 SilcStatus status, error;
725 SilcServerEntry entry = NULL;
726 SilcServerID *server_id;
730 COMMAND_CHECK_STATUS;
733 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
736 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
740 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
743 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
750 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
757 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
758 silc_server_command_reply_free(cmd);
764 /* Received reply for forwarded JOIN command. Router has created or joined
765 the client to the channel. We save some channel information locally
768 SILC_SERVER_CMD_REPLY_FUNC(join)
770 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
771 SilcServer server = cmd->server;
772 SilcIDCacheEntry cache = NULL;
773 SilcStatus status, error;
775 SilcClientID *client_id = NULL;
776 SilcChannelEntry entry;
777 SilcHmac hmac = NULL;
778 SilcUInt32 id_len, len, list_count;
779 unsigned char *id_string;
780 char *channel_name, *tmp;
781 SilcUInt32 mode, created;
782 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
784 COMMAND_CHECK_STATUS;
786 /* Get channel name */
787 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
792 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
797 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
800 client_id = silc_id_payload_parse_id(tmp, len, NULL);
805 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
808 SILC_GET32_MSB(mode, tmp);
810 /* Get created boolean value */
811 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
814 SILC_GET32_MSB(created, tmp);
815 if (created != 0 && created != 1)
818 /* Get channel key */
819 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
821 keyp = silc_buffer_alloc(len);
822 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
823 silc_buffer_put(keyp, tmp, len);
826 /* Parse the Channel ID */
827 id = silc_id_payload_parse_id(id_string, id_len, NULL);
832 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
834 if (!silc_hmac_alloc(tmp, NULL, &hmac))
838 /* Get the list count */
839 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
842 SILC_GET32_MSB(list_count, tmp);
844 /* Get Client ID list */
845 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
849 client_id_list = silc_buffer_alloc(len);
850 silc_buffer_pull_tail(client_id_list, len);
851 silc_buffer_put(client_id_list, tmp, len);
853 /* Get client mode list */
854 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
858 client_mode_list = silc_buffer_alloc(len);
859 silc_buffer_pull_tail(client_mode_list, len);
860 silc_buffer_put(client_mode_list, tmp, len);
862 /* See whether we already have the channel. */
863 entry = silc_idlist_find_channel_by_name(server->local_list,
864 channel_name, &cache);
866 /* Add new channel */
868 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
869 (created == 0 ? "existing" : "created"), channel_name,
870 silc_id_render(id, SILC_ID_CHANNEL)));
872 /* If the channel is found from global list we must move it to the
874 entry = silc_idlist_find_channel_by_name(server->global_list,
875 channel_name, &cache);
877 silc_idlist_del_channel(server->global_list, entry);
879 /* Add the channel to our local list. */
880 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
881 SILC_CHANNEL_MODE_NONE, id,
882 server->router, NULL, hmac, 0);
887 server->stat.my_channels++;
889 /* The entry exists. */
891 /* If ID has changed, then update it to the cache too. */
892 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
893 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
895 entry->disabled = FALSE;
897 /* Remove the founder auth data if the mode is not set but we have
899 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
900 silc_pkcs_public_key_free(entry->founder_key);
901 silc_free(entry->founder_passwd);
902 entry->founder_passwd = NULL;
906 if (entry->hmac_name && hmac) {
907 silc_free(entry->hmac_name);
908 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
911 /* Get the ban list */
912 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
914 silc_free(entry->ban_list);
915 entry->ban_list = silc_memdup(tmp, len);
918 /* Get the invite list */
919 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
921 silc_free(entry->invite_list);
922 entry->invite_list = silc_memdup(tmp, len);
926 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
928 silc_free(entry->topic);
929 entry->topic = strdup(tmp);
932 /* If channel was not created we know there is global users on the
934 entry->global_users = (created == 0 ? TRUE : FALSE);
936 /* If channel was just created the mask must be zero */
937 if (!entry->global_users && mode) {
938 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
939 "new channel, forcing it to zero", cmd->sock->hostname));
943 /* Save channel mode */
946 /* Save channel key */
948 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
949 silc_server_save_channel_key(server, keyp, entry);
950 silc_buffer_free(keyp);
953 /* Save the users to the channel */
954 silc_server_save_users_on_channel(server, cmd->sock, entry,
955 client_id, client_id_list,
956 client_mode_list, list_count);
957 entry->users_resolved = TRUE;
960 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
961 silc_free(client_id);
962 silc_server_command_reply_free(cmd);
965 silc_buffer_free(client_id_list);
966 if (client_mode_list)
967 silc_buffer_free(client_mode_list);
970 /* Received reply to STATS command. */
972 SILC_SERVER_CMD_REPLY_FUNC(stats)
974 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
975 SilcServer server = cmd->server;
976 SilcStatus status, error;
979 SilcBufferStruct buf;
981 COMMAND_CHECK_STATUS;
983 /* Get statistics structure */
984 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
985 if (server->server_type == SILC_SERVER && tmp) {
986 silc_buffer_set(&buf, tmp, tmp_len);
987 silc_buffer_unformat(&buf,
988 SILC_STR_UI_INT(NULL),
989 SILC_STR_UI_INT(NULL),
990 SILC_STR_UI_INT(NULL),
991 SILC_STR_UI_INT(NULL),
992 SILC_STR_UI_INT(NULL),
993 SILC_STR_UI_INT(NULL),
994 SILC_STR_UI_INT(&server->stat.cell_clients),
995 SILC_STR_UI_INT(&server->stat.cell_channels),
996 SILC_STR_UI_INT(&server->stat.cell_servers),
997 SILC_STR_UI_INT(&server->stat.clients),
998 SILC_STR_UI_INT(&server->stat.channels),
999 SILC_STR_UI_INT(&server->stat.servers),
1000 SILC_STR_UI_INT(&server->stat.routers),
1001 SILC_STR_UI_INT(&server->stat.server_ops),
1002 SILC_STR_UI_INT(&server->stat.router_ops),
1007 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1010 SILC_SERVER_CMD_REPLY_FUNC(users)
1012 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1013 SilcServer server = cmd->server;
1014 SilcStatus status, error;
1015 SilcChannelEntry channel;
1016 SilcChannelID *channel_id = NULL;
1017 SilcBuffer client_id_list;
1018 SilcBuffer client_mode_list;
1021 SilcUInt32 list_count;
1023 COMMAND_CHECK_STATUS;
1025 /* Get channel ID */
1026 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1029 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1033 /* Get channel entry */
1034 channel = silc_idlist_find_channel_by_id(server->local_list,
1037 channel = silc_idlist_find_channel_by_id(server->global_list,
1042 if (server->server_type != SILC_SERVER)
1045 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1046 silc_server_send_command(server, server->router->connection,
1047 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1048 1, 5, idp->data, idp->len);
1049 silc_buffer_free(idp);
1051 /* Register pending command callback. After we've received the channel
1052 information we will reprocess this command reply by re-calling this
1053 USERS command reply callback. */
1054 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1056 silc_server_command_reply_users, cmd);
1061 /* Get the list count */
1062 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1065 SILC_GET32_MSB(list_count, tmp);
1067 /* Get Client ID list */
1068 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1072 client_id_list = silc_buffer_alloc(tmp_len);
1073 silc_buffer_pull_tail(client_id_list, tmp_len);
1074 silc_buffer_put(client_id_list, tmp, tmp_len);
1076 /* Get client mode list */
1077 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1081 client_mode_list = silc_buffer_alloc(tmp_len);
1082 silc_buffer_pull_tail(client_mode_list, tmp_len);
1083 silc_buffer_put(client_mode_list, tmp, tmp_len);
1085 /* Save the users to the channel */
1086 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1087 client_id_list, client_mode_list,
1090 channel->global_users = silc_server_channel_has_global(channel);
1091 channel->users_resolved = TRUE;
1093 silc_buffer_free(client_id_list);
1094 silc_buffer_free(client_mode_list);
1097 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1098 silc_free(channel_id);
1099 silc_server_command_reply_free(cmd);
1102 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1104 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1105 SilcServer server = cmd->server;
1106 SilcStatus status, error;
1107 SilcClientEntry client = NULL;
1108 SilcServerEntry server_entry = NULL;
1109 SilcClientID *client_id = NULL;
1110 SilcServerID *server_id = NULL;
1112 unsigned char *tmp, *pk;
1115 SilcIDPayload idp = NULL;
1117 SilcPublicKey public_key = NULL;
1119 COMMAND_CHECK_STATUS;
1121 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1124 idp = silc_id_payload_parse(tmp, len);
1128 /* Get the public key payload */
1129 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1133 /* Decode the public key */
1135 SILC_GET16_MSB(pk_len, tmp);
1136 SILC_GET16_MSB(type, tmp + 2);
1139 if (type != SILC_SKE_PK_TYPE_SILC)
1142 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1145 id_type = silc_id_payload_get_type(idp);
1146 if (id_type == SILC_ID_CLIENT) {
1147 client_id = silc_id_payload_get_id(idp);
1149 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1152 client = silc_idlist_find_client_by_id(server->global_list,
1153 client_id, TRUE, NULL);
1158 client->data.public_key = public_key;
1160 } else if (id_type == SILC_ID_SERVER) {
1161 server_id = silc_id_payload_get_id(idp);
1163 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1165 if (!server_entry) {
1166 server_entry = silc_idlist_find_server_by_id(server->global_list,
1167 server_id, TRUE, NULL);
1172 server_entry->data.public_key = public_key;
1179 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1181 silc_id_payload_free(idp);
1182 silc_free(client_id);
1183 silc_free(server_id);
1185 silc_pkcs_public_key_free(public_key);
1186 silc_server_command_reply_free(cmd);
1189 SILC_SERVER_CMD_REPLY_FUNC(list)
1191 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1192 SilcServer server = cmd->server;
1193 SilcStatus status, error;
1194 SilcChannelID *channel_id = NULL;
1195 SilcChannelEntry channel;
1196 SilcIDCacheEntry cache;
1198 unsigned char *tmp, *name, *topic;
1199 SilcUInt32 usercount = 0;
1200 bool global_list = FALSE;
1202 COMMAND_CHECK_STATUS;
1204 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1205 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1209 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1210 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1211 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1213 SILC_GET32_MSB(usercount, tmp);
1215 /* Add the channel entry if we do not have it already */
1216 channel = silc_idlist_find_channel_by_name(server->local_list,
1219 channel = silc_idlist_find_channel_by_name(server->global_list,
1224 /* If router did not find such channel in its lists then this must
1225 be bogus channel or some router in the net is buggy. */
1226 if (server->server_type != SILC_SERVER)
1229 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1230 SILC_CHANNEL_MODE_NONE, channel_id,
1231 server->router, NULL, NULL,
1237 /* Found, update expiry */
1238 if (global_list && server->server_type == SILC_SERVER)
1239 cache->expire = time(NULL) + 60;
1242 channel->user_count = usercount;
1245 silc_free(channel->topic);
1246 channel->topic = strdup(topic);
1249 /* Pending callbacks are not executed if this was an list entry */
1250 if (status != SILC_STATUS_OK &&
1251 status != SILC_STATUS_LIST_END) {
1252 silc_server_command_reply_free(cmd);
1256 /* Now purge all old entries from the global list, otherwise we'll might
1257 have non-existent entries for long periods of time in the cache. */
1258 silc_idcache_purge(server->global_list->channels);
1261 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1262 silc_free(channel_id);
1263 silc_server_command_reply_free(cmd);