5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
24 #include "command_reply.h"
26 /* All functions that call the COMMAND_CHECK_STATUS macros must have
27 out: and err: goto labels. */
29 #define COMMAND_CHECK_STATUS \
31 SILC_LOG_DEBUG(("Start")); \
32 if (!silc_command_get_status(cmd->payload, &status, &error)) { \
33 if (SILC_STATUS_IS_ERROR(status)) \
35 if (status == SILC_STATUS_LIST_END) \
41 /* Server command reply list. Not all commands have reply function as
42 they are never sent by server. More maybe added later if need appears. */
43 SilcServerCommandReply silc_command_reply_list[] =
45 SILC_SERVER_CMD_REPLY(whois, WHOIS),
46 SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
47 SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
48 SILC_SERVER_CMD_REPLY(info, INFO),
49 SILC_SERVER_CMD_REPLY(motd, MOTD),
50 SILC_SERVER_CMD_REPLY(join, JOIN),
51 SILC_SERVER_CMD_REPLY(stats, STATS),
52 SILC_SERVER_CMD_REPLY(users, USERS),
53 SILC_SERVER_CMD_REPLY(getkey, GETKEY),
54 SILC_SERVER_CMD_REPLY(list, LIST),
59 /* Process received command reply. */
61 void silc_server_command_reply_process(SilcServer server,
62 SilcSocketConnection sock,
65 SilcServerCommandReply *cmd;
66 SilcServerCommandReplyContext ctx;
67 SilcCommandPayload payload;
70 SILC_LOG_DEBUG(("Start"));
72 /* Get command reply payload from packet */
73 payload = silc_command_payload_parse(buffer->data, buffer->len);
75 /* Silently ignore bad reply packet */
76 SILC_LOG_DEBUG(("Bad command reply packet"));
80 /* Allocate command reply context. This must be free'd by the
81 command reply routine receiving it. */
82 ctx = silc_calloc(1, sizeof(*ctx));
84 ctx->sock = silc_socket_dup(sock);
85 ctx->payload = payload;
86 ctx->args = silc_command_get_args(ctx->payload);
87 ctx->ident = silc_command_get_ident(ctx->payload);
89 /* Check for pending commands and mark to be exeucted */
91 silc_server_command_pending_check(server, silc_command_get(ctx->payload),
92 ctx->ident, &ctx->callbacks_count);
94 /* Execute command reply */
95 command = silc_command_get(ctx->payload);
96 for (cmd = silc_command_reply_list; cmd->cb; cmd++)
97 if (cmd->cmd == command)
100 if (cmd == NULL || !cmd->cb) {
101 silc_server_command_reply_free(ctx);
108 /* Free command reply context and its internals. */
110 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
113 silc_command_payload_free(cmd->payload);
115 silc_socket_free(cmd->sock); /* Decrease the reference counter */
116 silc_free(cmd->callbacks);
122 silc_server_command_process_error(SilcServerCommandReplyContext cmd,
125 SilcServer server = cmd->server;
127 /* If we received notify for invalid ID we'll remove the ID if we
129 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
130 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
131 SilcClientEntry client;
133 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
135 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
137 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
138 "the entry from cache"));
139 client = silc_idlist_find_client_by_id(server->global_list,
140 client_id, FALSE, NULL);
142 silc_server_remove_from_channels(server, NULL, client, TRUE,
144 silc_idlist_del_data(client);
145 silc_idlist_del_client(server->global_list, client);
147 silc_free(client_id);
153 /* Caches the received WHOIS information. */
156 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
158 SilcServer server = cmd->server;
159 unsigned char *tmp, *id_data, *umodes;
160 char *nickname, *username, *realname, *servername = NULL;
161 unsigned char *fingerprint;
162 SilcClientID *client_id;
163 SilcClientEntry client;
164 SilcIDCacheEntry cache = NULL;
167 SilcUInt32 mode = 0, len, len2, id_len, flen;
169 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
170 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
171 username = silc_argument_get_arg_type(cmd->args, 4, &len);
172 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
173 if (!id_data || !nickname || !username || !realname)
176 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
178 SILC_GET32_MSB(mode, tmp);
180 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
184 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
186 /* Check if we have this client cached already. */
188 client = silc_idlist_find_client_by_id(server->local_list, client_id,
191 client = silc_idlist_find_client_by_id(server->global_list, client_id,
197 /* If router did not find such Client ID in its lists then this must
198 be bogus client or some router in the net is buggy. */
199 if (server->server_type != SILC_SERVER)
202 /* Take hostname out of nick string if it includes it. */
203 silc_parse_userfqdn(nickname, &nick, &servername);
205 /* We don't have that client anywhere, add it. The client is added
206 to global list since server didn't have it in the lists so it must be
208 client = silc_idlist_add_client(server->global_list, nick,
210 strdup(realname), client_id,
211 cmd->sock->user_data, NULL, 0);
213 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
217 client->data.status |=
218 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
219 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
221 client->servername = servername;
223 /* We have the client already, update the data */
225 SILC_LOG_DEBUG(("Updating client data"));
227 /* Take hostname out of nick string if it includes it. */
228 silc_parse_userfqdn(nickname, &nick, &servername);
230 /* Remove the old cache entry */
231 silc_idcache_del_by_context(global ? server->global_list->clients :
232 server->local_list->clients, client);
234 silc_free(client->nickname);
235 silc_free(client->username);
236 silc_free(client->userinfo);
237 silc_free(client->servername);
239 client->nickname = nick;
240 client->username = strdup(username);
241 client->userinfo = strdup(realname);
242 client->servername = servername;
244 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
245 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
247 /* Create new cache entry */
248 silc_idcache_add(global ? server->global_list->clients :
249 server->local_list->clients, nick, client->id,
251 silc_free(client_id);
254 /* Save channel list if it was sent to us */
255 if (server->server_type == SILC_SERVER) {
256 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
257 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
259 SilcBufferStruct channels_buf, umodes_buf;
260 silc_buffer_set(&channels_buf, tmp, len);
261 silc_buffer_set(&umodes_buf, umodes, len2);
262 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
265 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
268 /* If client is global and is not on any channel then add that we'll
269 expire the entry after a while. */
271 silc_idlist_find_client_by_id(server->global_list, client->id,
273 if (!silc_hash_table_count(client->channels))
274 cache->expire = time(NULL) + 300;
280 if (fingerprint && flen == sizeof(client->data.fingerprint))
281 memcpy(client->data.fingerprint, fingerprint, flen);
286 /* Reiceved reply for WHOIS command. We sent the whois request to our
287 primary router, if we are normal server, and thus has now received reply
288 to the command. We will figure out what client originally sent us the
289 command and will send the reply to it. If we are router we will figure
290 out who server sent us the command and send reply to that one. */
292 SILC_SERVER_CMD_REPLY_FUNC(whois)
294 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
295 SilcStatus status, error;
297 COMMAND_CHECK_STATUS;
299 if (!silc_server_command_reply_whois_save(cmd))
302 /* Pending callbacks are not executed if this was an list entry */
303 if (status != SILC_STATUS_OK &&
304 status != SILC_STATUS_LIST_END) {
305 silc_server_command_reply_free(cmd);
310 silc_server_command_process_error(cmd, error);
311 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
312 silc_server_command_reply_free(cmd);
316 silc_server_command_process_error(cmd, error);
317 silc_server_command_reply_free(cmd);
320 /* Caches the received WHOWAS information for a short period of time. */
323 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
325 SilcServer server = cmd->server;
326 SilcUInt32 len, id_len;
327 unsigned char *id_data;
328 char *nickname, *username, *realname, *servername = NULL;
329 SilcClientID *client_id;
330 SilcClientEntry client;
331 SilcIDCacheEntry cache = NULL;
335 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
336 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
337 username = silc_argument_get_arg_type(cmd->args, 4, &len);
338 if (!id_data || !nickname || !username)
341 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
343 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
347 /* Check if we have this client cached already. */
349 client = silc_idlist_find_client_by_id(server->local_list, client_id,
352 client = silc_idlist_find_client_by_id(server->global_list,
353 client_id, FALSE, &cache);
358 /* If router did not find such Client ID in its lists then this must
359 be bogus client or some router in the net is buggy. */
360 if (server->server_type != SILC_SERVER)
363 /* Take hostname out of nick string if it includes it. */
364 silc_parse_userfqdn(nickname, &nick, &servername);
366 /* We don't have that client anywhere, add it. The client is added
367 to global list since server didn't have it in the lists so it must be
369 client = silc_idlist_add_client(server->global_list, nick,
370 strdup(username), strdup(realname),
371 silc_id_dup(client_id, SILC_ID_CLIENT),
372 cmd->sock->user_data, NULL,
373 SILC_ID_CACHE_EXPIRE_DEF);
375 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
379 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
380 client->servername = servername;
382 /* We have the client already, update the data */
384 /* Take hostname out of nick string if it includes it. */
385 silc_parse_userfqdn(nickname, &nick, &servername);
387 silc_free(client->nickname);
388 silc_free(client->username);
390 client->nickname = nick;
391 client->username = strdup(username);
392 client->servername = servername;
394 /* Remove the old cache entry and create a new one */
395 silc_idcache_del_by_context(global ? server->global_list->clients :
396 server->local_list->clients, client);
397 silc_idcache_add(global ? server->global_list->clients :
398 server->local_list->clients, nick, client->id,
402 /* If client is global and is not on any channel then add that we'll
403 expire the entry after a while. */
405 silc_idlist_find_client_by_id(server->global_list, client->id,
407 if (!silc_hash_table_count(client->channels))
408 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
413 silc_free(client_id);
418 /* Received reply for WHOWAS command. Cache the client information only for
419 a short period of time. */
421 SILC_SERVER_CMD_REPLY_FUNC(whowas)
423 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
424 SilcStatus status, error;
426 COMMAND_CHECK_STATUS;
428 if (!silc_server_command_reply_whowas_save(cmd))
431 /* Pending callbacks are not executed if this was an list entry */
432 if (status != SILC_STATUS_OK &&
433 status != SILC_STATUS_LIST_END) {
434 silc_server_command_reply_free(cmd);
439 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
441 silc_server_command_reply_free(cmd);
444 /* Caches the received IDENTIFY information. */
447 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
449 SilcServer server = cmd->server;
450 SilcUInt32 len, id_len;
451 unsigned char *id_data;
453 SilcClientID *client_id = NULL;
454 SilcServerID *server_id = NULL;
455 SilcChannelID *channel_id = NULL;
456 SilcClientEntry client;
457 SilcServerEntry server_entry;
458 SilcChannelEntry channel;
461 SilcIDPayload idp = NULL;
465 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
468 idp = silc_id_payload_parse(id_data, id_len);
472 name = silc_argument_get_arg_type(cmd->args, 3, &len);
473 info = silc_argument_get_arg_type(cmd->args, 4, &len);
475 id_type = silc_id_payload_get_type(idp);
479 client_id = silc_id_payload_get_id(idp);
483 SILC_LOG_DEBUG(("Received client information"));
485 client = silc_idlist_find_client_by_id(server->local_list,
486 client_id, FALSE, NULL);
488 client = silc_idlist_find_client_by_id(server->global_list, client_id,
493 /* If router did not find such Client ID in its lists then this must
494 be bogus client or some router in the net is buggy. */
495 if (server->server_type != SILC_SERVER)
500 silc_parse_userfqdn(name, &nick, NULL);
502 /* We don't have that client anywhere, add it. The client is added
503 to global list since server didn't have it in the lists so it must be
505 client = silc_idlist_add_client(server->global_list, nick,
506 info ? strdup(info) : NULL, NULL,
507 client_id, cmd->sock->user_data,
508 NULL, time(NULL) + 300);
510 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
513 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
514 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
515 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
517 /* We have the client already, update the data */
519 SILC_LOG_DEBUG(("Updating client data"));
523 silc_parse_userfqdn(name, &nick, NULL);
525 /* Remove the old cache entry */
526 silc_idcache_del_by_context(global ? server->global_list->clients :
527 server->local_list->clients, client);
529 silc_free(client->nickname);
530 client->nickname = nick;
534 silc_free(client->username);
535 client->username = strdup(info);
538 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
539 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
542 /* Add new cache entry */
543 silc_idcache_add(global ? server->global_list->clients :
544 server->local_list->clients, nick, client->id,
545 client, expire, NULL);
548 /* If client is global and is not on any channel then add that we'll
549 expire the entry after a while. */
550 if (global && server->server_type == SILC_SERVER) {
551 SilcIDCacheEntry cache = NULL;
552 silc_idlist_find_client_by_id(server->global_list, client->id,
554 if (!silc_hash_table_count(client->channels))
555 cache->expire = time(NULL) + 300;
560 silc_free(client_id);
569 server_id = silc_id_payload_get_id(idp);
573 SILC_LOG_DEBUG(("Received server information"));
575 server_entry = silc_idlist_find_server_by_id(server->local_list,
576 server_id, FALSE, NULL);
578 server_entry = silc_idlist_find_server_by_id(server->global_list,
579 server_id, FALSE, NULL);
581 /* If router did not find such Server ID in its lists then this must
582 be bogus server 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 server_entry = silc_idlist_add_server(server->global_list,
589 server_id, server->router,
590 SILC_PRIMARY_ROUTE(server));
592 silc_free(server_id);
595 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
596 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
597 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
601 silc_free(server_id);
604 case SILC_ID_CHANNEL:
608 channel_id = silc_id_payload_get_id(idp);
612 SILC_LOG_DEBUG(("Received channel information"));
614 channel = silc_idlist_find_channel_by_name(server->local_list,
617 channel = silc_idlist_find_channel_by_name(server->global_list,
620 /* If router did not find such Channel ID in its lists then this must
621 be bogus channel or some router in the net is buggy. */
622 if (server->server_type != SILC_SERVER)
625 /* We don't have that channel anywhere, add it. */
626 channel = silc_idlist_add_channel(server->global_list, strdup(name),
627 SILC_CHANNEL_MODE_NONE, channel_id,
628 server->router, NULL, NULL, 0);
630 silc_free(channel_id);
636 silc_free(channel_id);
640 silc_id_payload_free(idp);
644 silc_id_payload_free(idp);
648 /* Received reply for forwarded IDENTIFY command. We have received the
649 requested identify information now and we will cache it. After this we
650 will call the pending command so that the requestee gets the information
653 SILC_SERVER_CMD_REPLY_FUNC(identify)
655 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
656 SilcStatus status, error;
658 COMMAND_CHECK_STATUS;
660 if (!silc_server_command_reply_identify_save(cmd))
663 /* Pending callbacks are not executed if this was an list entry */
664 if (status != SILC_STATUS_OK &&
665 status != SILC_STATUS_LIST_END) {
666 silc_server_command_reply_free(cmd);
671 silc_server_command_process_error(cmd, error);
672 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
673 silc_server_command_reply_free(cmd);
677 silc_server_command_process_error(cmd, error);
678 silc_server_command_reply_free(cmd);
681 /* Received reply fro INFO command. Cache the server and its information */
683 SILC_SERVER_CMD_REPLY_FUNC(info)
685 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
686 SilcServer server = cmd->server;
687 SilcStatus status, error;
688 SilcServerEntry entry;
689 SilcServerID *server_id;
691 unsigned char *tmp, *name;
693 COMMAND_CHECK_STATUS;
696 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
699 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
704 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
708 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
711 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
714 /* Add the server to global list */
715 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
716 entry = silc_idlist_add_server(server->global_list, name, 0,
717 server_id, cmd->sock->user_data,
720 silc_free(server_id);
723 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
727 /* Get the info string */
728 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
732 entry->server_info = tmp ? strdup(tmp) : NULL;
735 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
737 silc_server_command_reply_free(cmd);
740 /* Received reply fro MOTD command. */
742 SILC_SERVER_CMD_REPLY_FUNC(motd)
744 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
745 SilcServer server = cmd->server;
746 SilcStatus status, error;
747 SilcServerEntry entry = NULL;
748 SilcServerID *server_id;
752 COMMAND_CHECK_STATUS;
755 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
758 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
762 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
765 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
772 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
779 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
781 silc_server_command_reply_free(cmd);
787 /* Received reply for forwarded JOIN command. Router has created or joined
788 the client to the channel. We save some channel information locally
791 SILC_SERVER_CMD_REPLY_FUNC(join)
793 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
794 SilcServer server = cmd->server;
795 SilcIDCacheEntry cache = NULL;
796 SilcStatus status, error;
798 SilcClientID *client_id = NULL;
799 SilcChannelEntry entry;
800 SilcHmac hmac = NULL;
801 SilcUInt32 id_len, len, list_count;
802 unsigned char *id_string;
803 char *channel_name, *tmp;
804 SilcUInt32 mode, created;
805 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
806 SilcPublicKey founder_key = NULL;
808 COMMAND_CHECK_STATUS;
810 /* Get channel name */
811 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
816 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
821 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
824 client_id = silc_id_payload_parse_id(tmp, len, NULL);
829 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
832 SILC_GET32_MSB(mode, tmp);
834 /* Get created boolean value */
835 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
838 SILC_GET32_MSB(created, tmp);
839 if (created != 0 && created != 1)
842 /* Get channel key */
843 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
845 keyp = silc_buffer_alloc(len);
846 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
847 silc_buffer_put(keyp, tmp, len);
850 /* Parse the Channel ID */
851 id = silc_id_payload_parse_id(id_string, id_len, NULL);
856 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
858 if (!silc_hmac_alloc(tmp, NULL, &hmac))
862 /* Get the list count */
863 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
866 SILC_GET32_MSB(list_count, tmp);
868 /* Get Client ID list */
869 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
873 client_id_list = silc_buffer_alloc(len);
874 silc_buffer_pull_tail(client_id_list, len);
875 silc_buffer_put(client_id_list, tmp, len);
877 /* Get client mode list */
878 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
882 client_mode_list = silc_buffer_alloc(len);
883 silc_buffer_pull_tail(client_mode_list, len);
884 silc_buffer_put(client_mode_list, tmp, len);
886 /* Get founder key */
887 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
889 silc_pkcs_public_key_decode(tmp, len, &founder_key);
891 /* See whether we already have the channel. */
892 entry = silc_idlist_find_channel_by_name(server->local_list,
893 channel_name, &cache);
895 /* Add new channel */
897 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
898 (created == 0 ? "existing" : "created"), channel_name,
899 silc_id_render(id, SILC_ID_CHANNEL)));
901 /* If the channel is found from global list we must move it to the
903 entry = silc_idlist_find_channel_by_name(server->global_list,
904 channel_name, &cache);
906 silc_idlist_del_channel(server->global_list, entry);
908 /* Add the channel to our local list. */
909 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
910 SILC_CHANNEL_MODE_NONE, id,
911 server->router, NULL, hmac, 0);
916 server->stat.my_channels++;
917 server->stat.channels++;
919 /* The entry exists. */
921 /* If ID has changed, then update it to the cache too. */
922 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
923 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
925 entry->disabled = FALSE;
927 /* Remove the founder auth data if the mode is not set but we have
929 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
930 silc_pkcs_public_key_free(entry->founder_key);
931 entry->founder_key = NULL;
936 if (entry->founder_key)
937 silc_pkcs_public_key_free(entry->founder_key);
938 entry->founder_key = founder_key;
942 if (entry->hmac_name && hmac) {
943 silc_free(entry->hmac_name);
944 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
947 /* Get the ban list */
948 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
950 silc_free(entry->ban_list);
951 entry->ban_list = silc_memdup(tmp, len);
954 /* Get the invite list */
955 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
957 silc_free(entry->invite_list);
958 entry->invite_list = silc_memdup(tmp, len);
962 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
964 silc_free(entry->topic);
965 entry->topic = strdup(tmp);
968 /* If channel was not created we know there is global users on the
970 entry->global_users = (created == 0 ? TRUE : FALSE);
972 /* If channel was just created the mask must be zero */
973 if (!entry->global_users && mode) {
974 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
975 "new channel, forcing it to zero", cmd->sock->hostname));
979 /* Save channel mode */
982 /* Save channel key */
984 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
985 silc_server_save_channel_key(server, keyp, entry);
986 silc_buffer_free(keyp);
989 /* Save the users to the channel */
990 silc_server_save_users_on_channel(server, cmd->sock, entry,
991 client_id, client_id_list,
992 client_mode_list, list_count);
993 entry->users_resolved = TRUE;
996 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
998 silc_free(client_id);
999 silc_server_command_reply_free(cmd);
1001 silc_pkcs_public_key_free(founder_key);
1003 silc_buffer_free(client_id_list);
1004 if (client_mode_list)
1005 silc_buffer_free(client_mode_list);
1008 /* Received reply to STATS command. */
1010 SILC_SERVER_CMD_REPLY_FUNC(stats)
1012 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1013 SilcServer server = cmd->server;
1014 SilcStatus status, error;
1017 SilcBufferStruct buf;
1019 COMMAND_CHECK_STATUS;
1021 /* Get statistics structure */
1022 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1023 if (server->server_type == SILC_SERVER && tmp) {
1024 silc_buffer_set(&buf, tmp, tmp_len);
1025 silc_buffer_unformat(&buf,
1026 SILC_STR_UI_INT(NULL),
1027 SILC_STR_UI_INT(NULL),
1028 SILC_STR_UI_INT(NULL),
1029 SILC_STR_UI_INT(NULL),
1030 SILC_STR_UI_INT(NULL),
1031 SILC_STR_UI_INT(NULL),
1032 SILC_STR_UI_INT(&server->stat.cell_clients),
1033 SILC_STR_UI_INT(&server->stat.cell_channels),
1034 SILC_STR_UI_INT(&server->stat.cell_servers),
1035 SILC_STR_UI_INT(&server->stat.clients),
1036 SILC_STR_UI_INT(&server->stat.channels),
1037 SILC_STR_UI_INT(&server->stat.servers),
1038 SILC_STR_UI_INT(&server->stat.routers),
1039 SILC_STR_UI_INT(&server->stat.server_ops),
1040 SILC_STR_UI_INT(&server->stat.router_ops),
1045 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1047 silc_server_command_reply_free(cmd);
1050 SILC_SERVER_CMD_REPLY_FUNC(users)
1052 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1053 SilcServer server = cmd->server;
1054 SilcStatus status, error;
1055 SilcChannelEntry channel;
1056 SilcChannelID *channel_id = NULL;
1057 SilcBuffer client_id_list;
1058 SilcBuffer client_mode_list;
1061 SilcUInt32 list_count;
1063 COMMAND_CHECK_STATUS;
1065 /* Get channel ID */
1066 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1069 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1073 /* Get channel entry */
1074 channel = silc_idlist_find_channel_by_id(server->local_list,
1077 channel = silc_idlist_find_channel_by_id(server->global_list,
1082 if (server->server_type != SILC_SERVER)
1085 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1086 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1087 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1088 1, 5, idp->data, idp->len);
1089 silc_buffer_free(idp);
1091 /* Register pending command callback. After we've received the channel
1092 information we will reprocess this command reply by re-calling this
1093 USERS command reply callback. */
1094 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1096 silc_server_command_reply_users, cmd);
1101 /* Get the list count */
1102 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1105 SILC_GET32_MSB(list_count, tmp);
1107 /* Get Client ID list */
1108 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1112 client_id_list = silc_buffer_alloc(tmp_len);
1113 silc_buffer_pull_tail(client_id_list, tmp_len);
1114 silc_buffer_put(client_id_list, tmp, tmp_len);
1116 /* Get client mode list */
1117 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1121 client_mode_list = silc_buffer_alloc(tmp_len);
1122 silc_buffer_pull_tail(client_mode_list, tmp_len);
1123 silc_buffer_put(client_mode_list, tmp, tmp_len);
1125 /* Save the users to the channel */
1126 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1127 client_id_list, client_mode_list,
1130 channel->global_users = silc_server_channel_has_global(channel);
1131 channel->users_resolved = TRUE;
1133 silc_buffer_free(client_id_list);
1134 silc_buffer_free(client_mode_list);
1137 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1138 silc_free(channel_id);
1140 silc_server_command_reply_free(cmd);
1143 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1145 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1146 SilcServer server = cmd->server;
1147 SilcStatus status, error;
1148 SilcClientEntry client = NULL;
1149 SilcServerEntry server_entry = NULL;
1150 SilcClientID *client_id = NULL;
1151 SilcServerID *server_id = NULL;
1153 unsigned char *tmp, *pk;
1156 SilcIDPayload idp = NULL;
1158 SilcPublicKey public_key = NULL;
1160 COMMAND_CHECK_STATUS;
1162 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1165 idp = silc_id_payload_parse(tmp, len);
1169 /* Get the public key payload */
1170 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1174 /* Decode the public key */
1176 SILC_GET16_MSB(pk_len, tmp);
1177 SILC_GET16_MSB(type, tmp + 2);
1180 if (type != SILC_SKE_PK_TYPE_SILC)
1183 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1186 id_type = silc_id_payload_get_type(idp);
1187 if (id_type == SILC_ID_CLIENT) {
1188 client_id = silc_id_payload_get_id(idp);
1190 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1193 client = silc_idlist_find_client_by_id(server->global_list,
1194 client_id, TRUE, NULL);
1199 client->data.public_key = public_key;
1201 } else if (id_type == SILC_ID_SERVER) {
1202 server_id = silc_id_payload_get_id(idp);
1204 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1206 if (!server_entry) {
1207 server_entry = silc_idlist_find_server_by_id(server->global_list,
1208 server_id, TRUE, NULL);
1213 server_entry->data.public_key = public_key;
1220 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1222 silc_id_payload_free(idp);
1223 silc_free(client_id);
1224 silc_free(server_id);
1226 silc_pkcs_public_key_free(public_key);
1228 silc_server_command_reply_free(cmd);
1231 SILC_SERVER_CMD_REPLY_FUNC(list)
1233 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1234 SilcServer server = cmd->server;
1235 SilcStatus status, error;
1236 SilcChannelID *channel_id = NULL;
1237 SilcChannelEntry channel;
1238 SilcIDCacheEntry cache;
1240 unsigned char *tmp, *name, *topic;
1241 SilcUInt32 usercount = 0;
1242 bool global_list = FALSE;
1244 COMMAND_CHECK_STATUS;
1246 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1247 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1251 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1252 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1253 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1255 SILC_GET32_MSB(usercount, tmp);
1257 /* Add the channel entry if we do not have it already */
1258 channel = silc_idlist_find_channel_by_name(server->local_list,
1261 channel = silc_idlist_find_channel_by_name(server->global_list,
1266 /* If router did not find such channel in its lists then this must
1267 be bogus channel or some router in the net is buggy. */
1268 if (server->server_type != SILC_SERVER)
1271 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1272 SILC_CHANNEL_MODE_NONE, channel_id,
1273 server->router, NULL, NULL,
1279 /* Found, update expiry */
1280 if (global_list && server->server_type == SILC_SERVER)
1281 cache->expire = time(NULL) + 60;
1284 channel->user_count = usercount;
1287 silc_free(channel->topic);
1288 channel->topic = strdup(topic);
1291 /* Pending callbacks are not executed if this was an list entry */
1292 if (status != SILC_STATUS_OK &&
1293 status != SILC_STATUS_LIST_END) {
1294 silc_server_command_reply_free(cmd);
1298 /* Now purge all old entries from the global list, otherwise we'll might
1299 have non-existent entries for long periods of time in the cache. */
1300 silc_idcache_purge(server->global_list->channels);
1303 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1304 silc_free(channel_id);
1306 silc_server_command_reply_free(cmd);
1309 SILC_SERVER_CMD_REPLY_FUNC(watch)
1311 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1312 SilcStatus status, error;
1314 COMMAND_CHECK_STATUS;
1317 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1319 silc_server_command_reply_free(cmd);