5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
24 #include "command_reply.h"
26 /* All functions that call the COMMAND_CHECK_STATUS macros must have
27 out: and err: goto labels. */
29 #define COMMAND_CHECK_STATUS \
31 SILC_LOG_DEBUG(("Start")); \
32 if (!silc_command_get_status(cmd->payload, &status, &error)) { \
33 if (SILC_STATUS_IS_ERROR(status)) \
35 if (status == SILC_STATUS_LIST_END) \
41 /* Server command reply list. Not all commands have reply function as
42 they are never sent by server. More maybe added later if need appears. */
43 SilcServerCommandReply silc_command_reply_list[] =
45 SILC_SERVER_CMD_REPLY(whois, WHOIS),
46 SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
47 SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
48 SILC_SERVER_CMD_REPLY(info, INFO),
49 SILC_SERVER_CMD_REPLY(motd, MOTD),
50 SILC_SERVER_CMD_REPLY(join, JOIN),
51 SILC_SERVER_CMD_REPLY(stats, STATS),
52 SILC_SERVER_CMD_REPLY(users, USERS),
53 SILC_SERVER_CMD_REPLY(getkey, GETKEY),
54 SILC_SERVER_CMD_REPLY(list, LIST),
59 /* Process received command reply. */
61 void silc_server_command_reply_process(SilcServer server,
62 SilcSocketConnection sock,
65 SilcServerCommandReply *cmd;
66 SilcServerCommandReplyContext ctx;
67 SilcCommandPayload payload;
71 SILC_LOG_DEBUG(("Start"));
73 /* Get command reply payload from packet */
74 payload = silc_command_payload_parse(buffer->data, buffer->len);
76 /* Silently ignore bad reply packet */
77 SILC_LOG_DEBUG(("Bad command reply packet"));
81 /* Allocate command reply context. This must be free'd by the
82 command reply routine receiving it. */
83 ctx = silc_calloc(1, sizeof(*ctx));
85 ctx->sock = silc_socket_dup(sock);
86 ctx->payload = payload;
87 ctx->args = silc_command_get_args(ctx->payload);
88 ident = silc_command_get_ident(ctx->payload);
90 /* Check for pending commands and mark to be exeucted */
92 silc_server_command_pending_check(server, ctx,
93 silc_command_get(ctx->payload),
94 ident, &ctx->callbacks_count);
96 /* Execute command reply */
97 command = silc_command_get(ctx->payload);
98 for (cmd = silc_command_reply_list; cmd->cb; cmd++)
99 if (cmd->cmd == command)
102 if (cmd == NULL || !cmd->cb) {
103 silc_server_command_reply_free(ctx);
110 /* Free command reply context and its internals. */
112 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
115 silc_command_payload_free(cmd->payload);
117 silc_socket_free(cmd->sock); /* Decrease the reference counter */
118 silc_free(cmd->callbacks);
124 silc_server_command_process_error(SilcServerCommandReplyContext cmd,
127 SilcServer server = cmd->server;
129 /* If we received notify for invalid ID we'll remove the ID if we
131 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
132 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
133 SilcClientEntry client;
135 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
137 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
139 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
140 "the entry from cache"));
141 client = silc_idlist_find_client_by_id(server->global_list,
142 client_id, FALSE, NULL);
144 silc_server_remove_from_channels(server, NULL, client, TRUE,
146 silc_idlist_del_client(server->global_list, client);
148 silc_free(client_id);
154 /* Caches the received WHOIS information. */
157 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
159 SilcServer server = cmd->server;
160 unsigned char *tmp, *id_data, *umodes;
161 char *nickname, *username, *realname, *servername = NULL;
162 unsigned char *fingerprint;
163 SilcClientID *client_id;
164 SilcClientEntry client;
165 SilcIDCacheEntry cache = NULL;
168 SilcUInt32 mode = 0, len, len2, id_len, flen;
170 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
171 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
172 username = silc_argument_get_arg_type(cmd->args, 4, &len);
173 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
174 if (!id_data || !nickname || !username || !realname)
177 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
179 SILC_GET32_MSB(mode, tmp);
181 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
185 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
187 /* Check if we have this client cached already. */
189 client = silc_idlist_find_client_by_id(server->local_list, client_id,
192 client = silc_idlist_find_client_by_id(server->global_list, client_id,
198 /* If router did not find such Client ID in its lists then this must
199 be bogus client or some router in the net is buggy. */
200 if (server->server_type != SILC_SERVER)
203 /* Take hostname out of nick string if it includes it. */
204 silc_parse_userfqdn(nickname, &nick, &servername);
206 /* We don't have that client anywhere, add it. The client is added
207 to global list since server didn't have it in the lists so it must be
209 client = silc_idlist_add_client(server->global_list, nick,
211 strdup(realname), client_id,
212 cmd->sock->user_data, NULL,
215 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
219 client->data.status |=
220 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
221 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
223 client->servername = servername;
225 /* We have the client already, update the data */
227 SILC_LOG_DEBUG(("Updating client data"));
229 /* Take hostname out of nick string if it includes it. */
230 silc_parse_userfqdn(nickname, &nick, &servername);
232 /* Remove the old cache entry */
233 silc_idcache_del_by_context(global ? server->global_list->clients :
234 server->local_list->clients, client);
236 silc_free(client->nickname);
237 silc_free(client->username);
238 silc_free(client->userinfo);
239 silc_free(client->servername);
241 client->nickname = nick;
242 client->username = strdup(username);
243 client->userinfo = strdup(realname);
244 client->servername = servername;
246 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
247 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
249 /* Create new cache entry */
250 silc_idcache_add(global ? server->global_list->clients :
251 server->local_list->clients, nick, client->id,
253 silc_free(client_id);
256 /* Save channel list if it was sent to us */
257 if (server->server_type == SILC_SERVER) {
258 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
259 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
261 SilcBufferStruct channels_buf, umodes_buf;
262 silc_buffer_set(&channels_buf, tmp, len);
263 silc_buffer_set(&umodes_buf, umodes, len2);
264 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
267 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
271 /* If client is global and is not on any channel then add that we'll
272 expire the entry after a while. */
273 if (global && !silc_hash_table_count(client->channels))
274 cache->expire = time(NULL) + 300;
277 if (fingerprint && flen == sizeof(client->data.fingerprint))
278 memcpy(client->data.fingerprint, fingerprint, flen);
283 /* Reiceved reply for WHOIS command. We sent the whois request to our
284 primary router, if we are normal server, and thus has now received reply
285 to the command. We will figure out what client originally sent us the
286 command and will send the reply to it. If we are router we will figure
287 out who server sent us the command and send reply to that one. */
289 SILC_SERVER_CMD_REPLY_FUNC(whois)
291 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
292 SilcStatus status, error;
294 COMMAND_CHECK_STATUS;
296 if (!silc_server_command_reply_whois_save(cmd))
299 /* Pending callbacks are not executed if this was an list entry */
300 if (status != SILC_STATUS_OK &&
301 status != SILC_STATUS_LIST_END) {
302 silc_server_command_reply_free(cmd);
307 silc_server_command_process_error(cmd, error);
308 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
309 silc_server_command_reply_free(cmd);
313 silc_server_command_process_error(cmd, error);
314 silc_server_command_reply_free(cmd);
317 /* Caches the received WHOWAS information for a short period of time. */
320 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
322 SilcServer server = cmd->server;
323 SilcUInt32 len, id_len;
324 unsigned char *id_data;
325 char *nickname, *username, *realname, *servername = NULL;
326 SilcClientID *client_id;
327 SilcClientEntry client;
328 SilcIDCacheEntry cache = NULL;
332 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
333 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
334 username = silc_argument_get_arg_type(cmd->args, 4, &len);
335 if (!id_data || !nickname || !username)
338 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
340 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
344 /* Check if we have this client cached already. */
346 client = silc_idlist_find_client_by_id(server->local_list, client_id,
349 client = silc_idlist_find_client_by_id(server->global_list,
350 client_id, FALSE, &cache);
355 /* If router did not find such Client ID in its lists then this must
356 be bogus client or some router in the net is buggy. */
357 if (server->server_type != SILC_SERVER)
360 /* Take hostname out of nick string if it includes it. */
361 silc_parse_userfqdn(nickname, &nick, &servername);
363 /* We don't have that client anywhere, add it. The client is added
364 to global list since server didn't have it in the lists so it must be
366 client = silc_idlist_add_client(server->global_list, nick,
367 strdup(username), strdup(realname),
368 silc_id_dup(client_id, SILC_ID_CLIENT),
369 cmd->sock->user_data, NULL,
370 SILC_ID_CACHE_EXPIRE_DEF);
372 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
376 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
377 client->servername = servername;
379 /* We have the client already, update the data */
381 /* Take hostname out of nick string if it includes it. */
382 silc_parse_userfqdn(nickname, &nick, &servername);
384 silc_free(client->nickname);
385 silc_free(client->username);
387 client->nickname = nick;
388 client->username = strdup(username);
389 client->servername = servername;
391 /* Remove the old cache entry and create a new one */
392 silc_idcache_del_by_context(global ? server->global_list->clients :
393 server->local_list->clients, client);
394 silc_idcache_add(global ? server->global_list->clients :
395 server->local_list->clients, nick, client->id,
399 silc_free(client_id);
404 /* Received reply for WHOWAS command. Cache the client information only for
405 a short period of time. */
407 SILC_SERVER_CMD_REPLY_FUNC(whowas)
409 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
410 SilcStatus status, error;
412 COMMAND_CHECK_STATUS;
414 if (!silc_server_command_reply_whowas_save(cmd))
417 /* Pending callbacks are not executed if this was an list entry */
418 if (status != SILC_STATUS_OK &&
419 status != SILC_STATUS_LIST_END) {
420 silc_server_command_reply_free(cmd);
425 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
427 silc_server_command_reply_free(cmd);
430 /* Caches the received IDENTIFY information. */
433 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
435 SilcServer server = cmd->server;
436 SilcUInt32 len, id_len;
437 unsigned char *id_data;
439 SilcClientID *client_id = NULL;
440 SilcServerID *server_id = NULL;
441 SilcChannelID *channel_id = NULL;
442 SilcClientEntry client;
443 SilcServerEntry server_entry;
444 SilcChannelEntry channel;
447 SilcIDPayload idp = NULL;
451 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
454 idp = silc_id_payload_parse(id_data, id_len);
458 name = silc_argument_get_arg_type(cmd->args, 3, &len);
459 info = silc_argument_get_arg_type(cmd->args, 4, &len);
461 id_type = silc_id_payload_get_type(idp);
465 client_id = silc_id_payload_get_id(idp);
469 SILC_LOG_DEBUG(("Received client information"));
471 client = silc_idlist_find_client_by_id(server->local_list,
472 client_id, FALSE, NULL);
474 client = silc_idlist_find_client_by_id(server->global_list, client_id,
479 /* If router did not find such Client ID in its lists then this must
480 be bogus client or some router in the net is buggy. */
481 if (server->server_type != SILC_SERVER)
486 silc_parse_userfqdn(name, &nick, NULL);
488 /* We don't have that client anywhere, add it. The client is added
489 to global list since server didn't have it in the lists so it must be
491 client = silc_idlist_add_client(server->global_list, nick,
492 info ? strdup(info) : NULL, NULL,
493 client_id, cmd->sock->user_data, NULL,
496 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
499 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
500 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
501 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
503 /* We have the client already, update the data */
505 SILC_LOG_DEBUG(("Updating client data"));
509 silc_parse_userfqdn(name, &nick, NULL);
511 /* Remove the old cache entry */
512 silc_idcache_del_by_context(global ? server->global_list->clients :
513 server->local_list->clients, client);
515 silc_free(client->nickname);
516 client->nickname = nick;
520 silc_free(client->username);
521 client->username = strdup(info);
524 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
525 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
528 /* If client is global and is not on any channel then add that we'll
529 expire the entry after a while. */
530 if (global && !silc_hash_table_count(client->channels) &&
531 server->server_type == SILC_SERVER)
532 expire = time(NULL) + 300;
534 /* Add new cache entry */
535 silc_idcache_add(global ? server->global_list->clients :
536 server->local_list->clients, nick, client->id,
537 client, expire, NULL);
540 silc_free(client_id);
549 server_id = silc_id_payload_get_id(idp);
553 SILC_LOG_DEBUG(("Received server information"));
555 server_entry = silc_idlist_find_server_by_id(server->local_list,
556 server_id, FALSE, NULL);
558 server_entry = silc_idlist_find_server_by_id(server->global_list,
559 server_id, FALSE, NULL);
561 /* If router did not find such Server ID in its lists then this must
562 be bogus server or some router in the net is buggy. */
563 if (server->server_type != SILC_SERVER)
566 /* We don't have that server anywhere, add it. */
567 server_entry = silc_idlist_add_server(server->global_list,
569 server_id, server->router,
570 SILC_PRIMARY_ROUTE(server));
572 silc_free(server_id);
575 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
576 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
577 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
581 silc_free(server_id);
584 case SILC_ID_CHANNEL:
588 channel_id = silc_id_payload_get_id(idp);
592 SILC_LOG_DEBUG(("Received channel information"));
594 channel = silc_idlist_find_channel_by_name(server->local_list,
597 channel = silc_idlist_find_channel_by_name(server->global_list,
600 /* If router did not find such Channel ID in its lists then this must
601 be bogus channel or some router in the net is buggy. */
602 if (server->server_type != SILC_SERVER)
605 /* We don't have that channel anywhere, add it. */
606 channel = silc_idlist_add_channel(server->global_list, strdup(name),
607 SILC_CHANNEL_MODE_NONE, channel_id,
608 server->router, NULL, NULL, 0);
610 silc_free(channel_id);
616 silc_free(channel_id);
620 silc_id_payload_free(idp);
624 silc_id_payload_free(idp);
628 /* Received reply for forwarded IDENTIFY command. We have received the
629 requested identify information now and we will cache it. After this we
630 will call the pending command so that the requestee gets the information
633 SILC_SERVER_CMD_REPLY_FUNC(identify)
635 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
636 SilcStatus status, error;
638 COMMAND_CHECK_STATUS;
640 if (!silc_server_command_reply_identify_save(cmd))
643 /* Pending callbacks are not executed if this was an list entry */
644 if (status != SILC_STATUS_OK &&
645 status != SILC_STATUS_LIST_END) {
646 silc_server_command_reply_free(cmd);
651 silc_server_command_process_error(cmd, error);
652 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
653 silc_server_command_reply_free(cmd);
657 silc_server_command_process_error(cmd, error);
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, cmd->sock->user_data,
700 silc_free(server_id);
703 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
707 /* Get the info string */
708 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
712 entry->server_info = tmp ? strdup(tmp) : NULL;
715 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
717 silc_server_command_reply_free(cmd);
720 /* Received reply fro MOTD command. */
722 SILC_SERVER_CMD_REPLY_FUNC(motd)
724 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
725 SilcServer server = cmd->server;
726 SilcStatus status, error;
727 SilcServerEntry entry = NULL;
728 SilcServerID *server_id;
732 COMMAND_CHECK_STATUS;
735 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
738 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
742 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
745 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
752 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
759 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
761 silc_server_command_reply_free(cmd);
767 /* Received reply for forwarded JOIN command. Router has created or joined
768 the client to the channel. We save some channel information locally
771 SILC_SERVER_CMD_REPLY_FUNC(join)
773 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
774 SilcServer server = cmd->server;
775 SilcIDCacheEntry cache = NULL;
776 SilcStatus status, error;
778 SilcClientID *client_id = NULL;
779 SilcChannelEntry entry;
780 SilcHmac hmac = NULL;
781 SilcUInt32 id_len, len, list_count;
782 unsigned char *id_string;
783 char *channel_name, *tmp;
784 SilcUInt32 mode, created;
785 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
786 SilcPublicKey founder_key = NULL;
788 COMMAND_CHECK_STATUS;
790 /* Get channel name */
791 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
796 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
801 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
804 client_id = silc_id_payload_parse_id(tmp, len, NULL);
809 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
812 SILC_GET32_MSB(mode, tmp);
814 /* Get created boolean value */
815 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
818 SILC_GET32_MSB(created, tmp);
819 if (created != 0 && created != 1)
822 /* Get channel key */
823 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
825 keyp = silc_buffer_alloc(len);
826 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
827 silc_buffer_put(keyp, tmp, len);
830 /* Parse the Channel ID */
831 id = silc_id_payload_parse_id(id_string, id_len, NULL);
836 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
838 if (!silc_hmac_alloc(tmp, NULL, &hmac))
842 /* Get the list count */
843 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
846 SILC_GET32_MSB(list_count, tmp);
848 /* Get Client ID list */
849 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
853 client_id_list = silc_buffer_alloc(len);
854 silc_buffer_pull_tail(client_id_list, len);
855 silc_buffer_put(client_id_list, tmp, len);
857 /* Get client mode list */
858 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
862 client_mode_list = silc_buffer_alloc(len);
863 silc_buffer_pull_tail(client_mode_list, len);
864 silc_buffer_put(client_mode_list, tmp, len);
866 /* Get founder key */
867 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
869 silc_pkcs_public_key_decode(tmp, len, &founder_key);
871 /* See whether we already have the channel. */
872 entry = silc_idlist_find_channel_by_name(server->local_list,
873 channel_name, &cache);
875 /* Add new channel */
877 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
878 (created == 0 ? "existing" : "created"), channel_name,
879 silc_id_render(id, SILC_ID_CHANNEL)));
881 /* If the channel is found from global list we must move it to the
883 entry = silc_idlist_find_channel_by_name(server->global_list,
884 channel_name, &cache);
886 silc_idlist_del_channel(server->global_list, entry);
888 /* Add the channel to our local list. */
889 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
890 SILC_CHANNEL_MODE_NONE, id,
891 server->router, NULL, hmac, 0);
896 server->stat.my_channels++;
897 server->stat.channels++;
899 /* The entry exists. */
901 /* If ID has changed, then update it to the cache too. */
902 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
903 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
905 entry->disabled = FALSE;
907 /* Remove the founder auth data if the mode is not set but we have
909 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
910 silc_pkcs_public_key_free(entry->founder_key);
911 entry->founder_key = NULL;
916 if (entry->founder_key)
917 silc_pkcs_public_key_free(entry->founder_key);
918 entry->founder_key = founder_key;
922 if (entry->hmac_name && hmac) {
923 silc_free(entry->hmac_name);
924 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
927 /* Get the ban list */
928 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
930 silc_free(entry->ban_list);
931 entry->ban_list = silc_memdup(tmp, len);
934 /* Get the invite list */
935 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
937 silc_free(entry->invite_list);
938 entry->invite_list = silc_memdup(tmp, len);
942 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
944 silc_free(entry->topic);
945 entry->topic = strdup(tmp);
948 /* If channel was not created we know there is global users on the
950 entry->global_users = (created == 0 ? TRUE : FALSE);
952 /* If channel was just created the mask must be zero */
953 if (!entry->global_users && mode) {
954 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
955 "new channel, forcing it to zero", cmd->sock->hostname));
959 /* Save channel mode */
962 /* Save channel key */
964 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
965 silc_server_save_channel_key(server, keyp, entry);
966 silc_buffer_free(keyp);
969 /* Save the users to the channel */
970 silc_server_save_users_on_channel(server, cmd->sock, entry,
971 client_id, client_id_list,
972 client_mode_list, list_count);
973 entry->users_resolved = TRUE;
976 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
978 silc_free(client_id);
979 silc_server_command_reply_free(cmd);
981 silc_pkcs_public_key_free(founder_key);
983 silc_buffer_free(client_id_list);
984 if (client_mode_list)
985 silc_buffer_free(client_mode_list);
988 /* Received reply to STATS command. */
990 SILC_SERVER_CMD_REPLY_FUNC(stats)
992 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
993 SilcServer server = cmd->server;
994 SilcStatus status, error;
997 SilcBufferStruct buf;
999 COMMAND_CHECK_STATUS;
1001 /* Get statistics structure */
1002 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1003 if (server->server_type == SILC_SERVER && tmp) {
1004 silc_buffer_set(&buf, tmp, tmp_len);
1005 silc_buffer_unformat(&buf,
1006 SILC_STR_UI_INT(NULL),
1007 SILC_STR_UI_INT(NULL),
1008 SILC_STR_UI_INT(NULL),
1009 SILC_STR_UI_INT(NULL),
1010 SILC_STR_UI_INT(NULL),
1011 SILC_STR_UI_INT(NULL),
1012 SILC_STR_UI_INT(&server->stat.cell_clients),
1013 SILC_STR_UI_INT(&server->stat.cell_channels),
1014 SILC_STR_UI_INT(&server->stat.cell_servers),
1015 SILC_STR_UI_INT(&server->stat.clients),
1016 SILC_STR_UI_INT(&server->stat.channels),
1017 SILC_STR_UI_INT(&server->stat.servers),
1018 SILC_STR_UI_INT(&server->stat.routers),
1019 SILC_STR_UI_INT(&server->stat.server_ops),
1020 SILC_STR_UI_INT(&server->stat.router_ops),
1025 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1027 silc_server_command_reply_free(cmd);
1030 SILC_SERVER_CMD_REPLY_FUNC(users)
1032 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1033 SilcServer server = cmd->server;
1034 SilcStatus status, error;
1035 SilcChannelEntry channel;
1036 SilcChannelID *channel_id = NULL;
1037 SilcBuffer client_id_list;
1038 SilcBuffer client_mode_list;
1041 SilcUInt32 list_count;
1043 COMMAND_CHECK_STATUS;
1045 /* Get channel ID */
1046 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1049 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1053 /* Get channel entry */
1054 channel = silc_idlist_find_channel_by_id(server->local_list,
1057 channel = silc_idlist_find_channel_by_id(server->global_list,
1062 if (server->server_type != SILC_SERVER)
1065 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1066 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1067 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1068 1, 5, idp->data, idp->len);
1069 silc_buffer_free(idp);
1071 /* Register pending command callback. After we've received the channel
1072 information we will reprocess this command reply by re-calling this
1073 USERS command reply callback. */
1074 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1076 silc_server_command_reply_users, cmd);
1081 /* Get the list count */
1082 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1085 SILC_GET32_MSB(list_count, tmp);
1087 /* Get Client ID list */
1088 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1092 client_id_list = silc_buffer_alloc(tmp_len);
1093 silc_buffer_pull_tail(client_id_list, tmp_len);
1094 silc_buffer_put(client_id_list, tmp, tmp_len);
1096 /* Get client mode list */
1097 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1101 client_mode_list = silc_buffer_alloc(tmp_len);
1102 silc_buffer_pull_tail(client_mode_list, tmp_len);
1103 silc_buffer_put(client_mode_list, tmp, tmp_len);
1105 /* Save the users to the channel */
1106 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1107 client_id_list, client_mode_list,
1110 channel->global_users = silc_server_channel_has_global(channel);
1111 channel->users_resolved = TRUE;
1113 silc_buffer_free(client_id_list);
1114 silc_buffer_free(client_mode_list);
1117 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1118 silc_free(channel_id);
1120 silc_server_command_reply_free(cmd);
1123 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1125 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1126 SilcServer server = cmd->server;
1127 SilcStatus status, error;
1128 SilcClientEntry client = NULL;
1129 SilcServerEntry server_entry = NULL;
1130 SilcClientID *client_id = NULL;
1131 SilcServerID *server_id = NULL;
1133 unsigned char *tmp, *pk;
1136 SilcIDPayload idp = NULL;
1138 SilcPublicKey public_key = NULL;
1140 COMMAND_CHECK_STATUS;
1142 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1145 idp = silc_id_payload_parse(tmp, len);
1149 /* Get the public key payload */
1150 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1154 /* Decode the public key */
1156 SILC_GET16_MSB(pk_len, tmp);
1157 SILC_GET16_MSB(type, tmp + 2);
1160 if (type != SILC_SKE_PK_TYPE_SILC)
1163 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1166 id_type = silc_id_payload_get_type(idp);
1167 if (id_type == SILC_ID_CLIENT) {
1168 client_id = silc_id_payload_get_id(idp);
1170 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1173 client = silc_idlist_find_client_by_id(server->global_list,
1174 client_id, TRUE, NULL);
1179 client->data.public_key = public_key;
1181 } else if (id_type == SILC_ID_SERVER) {
1182 server_id = silc_id_payload_get_id(idp);
1184 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1186 if (!server_entry) {
1187 server_entry = silc_idlist_find_server_by_id(server->global_list,
1188 server_id, TRUE, NULL);
1193 server_entry->data.public_key = public_key;
1200 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1202 silc_id_payload_free(idp);
1203 silc_free(client_id);
1204 silc_free(server_id);
1206 silc_pkcs_public_key_free(public_key);
1208 silc_server_command_reply_free(cmd);
1211 SILC_SERVER_CMD_REPLY_FUNC(list)
1213 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1214 SilcServer server = cmd->server;
1215 SilcStatus status, error;
1216 SilcChannelID *channel_id = NULL;
1217 SilcChannelEntry channel;
1218 SilcIDCacheEntry cache;
1220 unsigned char *tmp, *name, *topic;
1221 SilcUInt32 usercount = 0;
1222 bool global_list = FALSE;
1224 COMMAND_CHECK_STATUS;
1226 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1227 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1231 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1232 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1233 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1235 SILC_GET32_MSB(usercount, tmp);
1237 /* Add the channel entry if we do not have it already */
1238 channel = silc_idlist_find_channel_by_name(server->local_list,
1241 channel = silc_idlist_find_channel_by_name(server->global_list,
1246 /* If router did not find such channel in its lists then this must
1247 be bogus channel or some router in the net is buggy. */
1248 if (server->server_type != SILC_SERVER)
1251 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1252 SILC_CHANNEL_MODE_NONE, channel_id,
1253 server->router, NULL, NULL,
1259 /* Found, update expiry */
1260 if (global_list && server->server_type == SILC_SERVER)
1261 cache->expire = time(NULL) + 60;
1264 channel->user_count = usercount;
1267 silc_free(channel->topic);
1268 channel->topic = strdup(topic);
1271 /* Pending callbacks are not executed if this was an list entry */
1272 if (status != SILC_STATUS_OK &&
1273 status != SILC_STATUS_LIST_END) {
1274 silc_server_command_reply_free(cmd);
1278 /* Now purge all old entries from the global list, otherwise we'll might
1279 have non-existent entries for long periods of time in the cache. */
1280 silc_idcache_purge(server->global_list->channels);
1283 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1284 silc_free(channel_id);
1286 silc_server_command_reply_free(cmd);
1289 SILC_SERVER_CMD_REPLY_FUNC(watch)
1291 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1292 SilcStatus status, error;
1294 COMMAND_CHECK_STATUS;
1297 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1299 silc_server_command_reply_free(cmd);