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_data(client);
147 silc_idlist_del_client(server->global_list, client);
149 silc_free(client_id);
155 /* Caches the received WHOIS information. */
158 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
160 SilcServer server = cmd->server;
161 unsigned char *tmp, *id_data, *umodes;
162 char *nickname, *username, *realname, *servername = NULL;
163 unsigned char *fingerprint;
164 SilcClientID *client_id;
165 SilcClientEntry client;
166 SilcIDCacheEntry cache = NULL;
169 SilcUInt32 mode = 0, len, len2, id_len, flen;
171 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
172 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
173 username = silc_argument_get_arg_type(cmd->args, 4, &len);
174 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
175 if (!id_data || !nickname || !username || !realname)
178 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
180 SILC_GET32_MSB(mode, tmp);
182 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
186 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
188 /* Check if we have this client cached already. */
190 client = silc_idlist_find_client_by_id(server->local_list, client_id,
193 client = silc_idlist_find_client_by_id(server->global_list, client_id,
199 /* If router did not find such Client ID in its lists then this must
200 be bogus client or some router in the net is buggy. */
201 if (server->server_type != SILC_SERVER)
204 /* Take hostname out of nick string if it includes it. */
205 silc_parse_userfqdn(nickname, &nick, &servername);
207 /* We don't have that client anywhere, add it. The client is added
208 to global list since server didn't have it in the lists so it must be
210 client = silc_idlist_add_client(server->global_list, nick,
212 strdup(realname), client_id,
213 cmd->sock->user_data, NULL, 0);
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);
270 /* If client is global and is not on any channel then add that we'll
271 expire the entry after a while. */
273 silc_idlist_find_client_by_id(server->global_list, client->id,
275 if (!silc_hash_table_count(client->channels))
276 cache->expire = time(NULL) + 300;
282 if (fingerprint && flen == sizeof(client->data.fingerprint))
283 memcpy(client->data.fingerprint, fingerprint, flen);
288 /* Reiceved reply for WHOIS command. We sent the whois request to our
289 primary router, if we are normal server, and thus has now received reply
290 to the command. We will figure out what client originally sent us the
291 command and will send the reply to it. If we are router we will figure
292 out who server sent us the command and send reply to that one. */
294 SILC_SERVER_CMD_REPLY_FUNC(whois)
296 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
297 SilcStatus status, error;
299 COMMAND_CHECK_STATUS;
301 if (!silc_server_command_reply_whois_save(cmd))
304 /* Pending callbacks are not executed if this was an list entry */
305 if (status != SILC_STATUS_OK &&
306 status != SILC_STATUS_LIST_END) {
307 silc_server_command_reply_free(cmd);
312 silc_server_command_process_error(cmd, error);
313 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
314 silc_server_command_reply_free(cmd);
318 silc_server_command_process_error(cmd, error);
319 silc_server_command_reply_free(cmd);
322 /* Caches the received WHOWAS information for a short period of time. */
325 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
327 SilcServer server = cmd->server;
328 SilcUInt32 len, id_len;
329 unsigned char *id_data;
330 char *nickname, *username, *realname, *servername = NULL;
331 SilcClientID *client_id;
332 SilcClientEntry client;
333 SilcIDCacheEntry cache = NULL;
337 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
338 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
339 username = silc_argument_get_arg_type(cmd->args, 4, &len);
340 if (!id_data || !nickname || !username)
343 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
345 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
349 /* Check if we have this client cached already. */
351 client = silc_idlist_find_client_by_id(server->local_list, client_id,
354 client = silc_idlist_find_client_by_id(server->global_list,
355 client_id, FALSE, &cache);
360 /* If router did not find such Client ID in its lists then this must
361 be bogus client or some router in the net is buggy. */
362 if (server->server_type != SILC_SERVER)
365 /* Take hostname out of nick string if it includes it. */
366 silc_parse_userfqdn(nickname, &nick, &servername);
368 /* We don't have that client anywhere, add it. The client is added
369 to global list since server didn't have it in the lists so it must be
371 client = silc_idlist_add_client(server->global_list, nick,
372 strdup(username), strdup(realname),
373 silc_id_dup(client_id, SILC_ID_CLIENT),
374 cmd->sock->user_data, NULL,
375 SILC_ID_CACHE_EXPIRE_DEF);
377 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
381 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
382 client->servername = servername;
384 /* We have the client already, update the data */
386 /* Take hostname out of nick string if it includes it. */
387 silc_parse_userfqdn(nickname, &nick, &servername);
389 silc_free(client->nickname);
390 silc_free(client->username);
392 client->nickname = nick;
393 client->username = strdup(username);
394 client->servername = servername;
396 /* Remove the old cache entry and create a new one */
397 silc_idcache_del_by_context(global ? server->global_list->clients :
398 server->local_list->clients, client);
399 silc_idcache_add(global ? server->global_list->clients :
400 server->local_list->clients, nick, client->id,
404 /* If client is global and is not on any channel then add that we'll
405 expire the entry after a while. */
407 silc_idlist_find_client_by_id(server->global_list, client->id,
409 if (!silc_hash_table_count(client->channels))
410 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
415 silc_free(client_id);
420 /* Received reply for WHOWAS command. Cache the client information only for
421 a short period of time. */
423 SILC_SERVER_CMD_REPLY_FUNC(whowas)
425 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
426 SilcStatus status, error;
428 COMMAND_CHECK_STATUS;
430 if (!silc_server_command_reply_whowas_save(cmd))
433 /* Pending callbacks are not executed if this was an list entry */
434 if (status != SILC_STATUS_OK &&
435 status != SILC_STATUS_LIST_END) {
436 silc_server_command_reply_free(cmd);
441 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
443 silc_server_command_reply_free(cmd);
446 /* Caches the received IDENTIFY information. */
449 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
451 SilcServer server = cmd->server;
452 SilcUInt32 len, id_len;
453 unsigned char *id_data;
455 SilcClientID *client_id = NULL;
456 SilcServerID *server_id = NULL;
457 SilcChannelID *channel_id = NULL;
458 SilcClientEntry client;
459 SilcServerEntry server_entry;
460 SilcChannelEntry channel;
463 SilcIDPayload idp = NULL;
467 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
470 idp = silc_id_payload_parse(id_data, id_len);
474 name = silc_argument_get_arg_type(cmd->args, 3, &len);
475 info = silc_argument_get_arg_type(cmd->args, 4, &len);
477 id_type = silc_id_payload_get_type(idp);
481 client_id = silc_id_payload_get_id(idp);
485 SILC_LOG_DEBUG(("Received client information"));
487 client = silc_idlist_find_client_by_id(server->local_list,
488 client_id, FALSE, NULL);
490 client = silc_idlist_find_client_by_id(server->global_list, client_id,
495 /* If router did not find such Client ID in its lists then this must
496 be bogus client or some router in the net is buggy. */
497 if (server->server_type != SILC_SERVER)
502 silc_parse_userfqdn(name, &nick, NULL);
504 /* We don't have that client anywhere, add it. The client is added
505 to global list since server didn't have it in the lists so it must be
507 client = silc_idlist_add_client(server->global_list, nick,
508 info ? strdup(info) : NULL, NULL,
509 client_id, cmd->sock->user_data,
510 NULL, time(NULL) + 300);
512 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
515 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
516 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
517 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
519 /* We have the client already, update the data */
521 SILC_LOG_DEBUG(("Updating client data"));
525 silc_parse_userfqdn(name, &nick, NULL);
527 /* Remove the old cache entry */
528 silc_idcache_del_by_context(global ? server->global_list->clients :
529 server->local_list->clients, client);
531 silc_free(client->nickname);
532 client->nickname = nick;
536 silc_free(client->username);
537 client->username = strdup(info);
540 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
541 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
544 /* Add new cache entry */
545 silc_idcache_add(global ? server->global_list->clients :
546 server->local_list->clients, nick, client->id,
547 client, expire, NULL);
550 /* If client is global and is not on any channel then add that we'll
551 expire the entry after a while. */
552 if (global && server->server_type == SILC_SERVER) {
553 SilcIDCacheEntry cache = NULL;
554 silc_idlist_find_client_by_id(server->global_list, client->id,
556 if (!silc_hash_table_count(client->channels))
557 cache->expire = time(NULL) + 300;
562 silc_free(client_id);
571 server_id = silc_id_payload_get_id(idp);
575 SILC_LOG_DEBUG(("Received server information"));
577 server_entry = silc_idlist_find_server_by_id(server->local_list,
578 server_id, FALSE, NULL);
580 server_entry = silc_idlist_find_server_by_id(server->global_list,
581 server_id, FALSE, NULL);
583 /* If router did not find such Server ID in its lists then this must
584 be bogus server or some router in the net is buggy. */
585 if (server->server_type != SILC_SERVER)
588 /* We don't have that server anywhere, add it. */
589 server_entry = silc_idlist_add_server(server->global_list,
591 server_id, server->router,
592 SILC_PRIMARY_ROUTE(server));
594 silc_free(server_id);
597 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
598 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
599 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
603 silc_free(server_id);
606 case SILC_ID_CHANNEL:
610 channel_id = silc_id_payload_get_id(idp);
614 SILC_LOG_DEBUG(("Received channel information"));
616 channel = silc_idlist_find_channel_by_name(server->local_list,
619 channel = silc_idlist_find_channel_by_name(server->global_list,
622 /* If router did not find such Channel ID in its lists then this must
623 be bogus channel or some router in the net is buggy. */
624 if (server->server_type != SILC_SERVER)
627 /* We don't have that channel anywhere, add it. */
628 channel = silc_idlist_add_channel(server->global_list, strdup(name),
629 SILC_CHANNEL_MODE_NONE, channel_id,
630 server->router, NULL, NULL, 0);
632 silc_free(channel_id);
638 silc_free(channel_id);
642 silc_id_payload_free(idp);
646 silc_id_payload_free(idp);
650 /* Received reply for forwarded IDENTIFY command. We have received the
651 requested identify information now and we will cache it. After this we
652 will call the pending command so that the requestee gets the information
655 SILC_SERVER_CMD_REPLY_FUNC(identify)
657 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
658 SilcStatus status, error;
660 COMMAND_CHECK_STATUS;
662 if (!silc_server_command_reply_identify_save(cmd))
665 /* Pending callbacks are not executed if this was an list entry */
666 if (status != SILC_STATUS_OK &&
667 status != SILC_STATUS_LIST_END) {
668 silc_server_command_reply_free(cmd);
673 silc_server_command_process_error(cmd, error);
674 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
675 silc_server_command_reply_free(cmd);
679 silc_server_command_process_error(cmd, error);
680 silc_server_command_reply_free(cmd);
683 /* Received reply fro INFO command. Cache the server and its information */
685 SILC_SERVER_CMD_REPLY_FUNC(info)
687 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
688 SilcServer server = cmd->server;
689 SilcStatus status, error;
690 SilcServerEntry entry;
691 SilcServerID *server_id;
693 unsigned char *tmp, *name;
695 COMMAND_CHECK_STATUS;
698 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
701 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
706 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
710 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
713 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
716 /* Add the server to global list */
717 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
718 entry = silc_idlist_add_server(server->global_list, name, 0,
719 server_id, cmd->sock->user_data,
722 silc_free(server_id);
725 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
729 /* Get the info string */
730 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
734 entry->server_info = tmp ? strdup(tmp) : NULL;
737 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
739 silc_server_command_reply_free(cmd);
742 /* Received reply fro MOTD command. */
744 SILC_SERVER_CMD_REPLY_FUNC(motd)
746 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
747 SilcServer server = cmd->server;
748 SilcStatus status, error;
749 SilcServerEntry entry = NULL;
750 SilcServerID *server_id;
754 COMMAND_CHECK_STATUS;
757 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
760 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
764 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
767 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
774 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
781 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
783 silc_server_command_reply_free(cmd);
789 /* Received reply for forwarded JOIN command. Router has created or joined
790 the client to the channel. We save some channel information locally
793 SILC_SERVER_CMD_REPLY_FUNC(join)
795 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
796 SilcServer server = cmd->server;
797 SilcIDCacheEntry cache = NULL;
798 SilcStatus status, error;
800 SilcClientID *client_id = NULL;
801 SilcChannelEntry entry;
802 SilcHmac hmac = NULL;
803 SilcUInt32 id_len, len, list_count;
804 unsigned char *id_string;
805 char *channel_name, *tmp;
806 SilcUInt32 mode, created;
807 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
808 SilcPublicKey founder_key = NULL;
810 COMMAND_CHECK_STATUS;
812 /* Get channel name */
813 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
818 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
823 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
826 client_id = silc_id_payload_parse_id(tmp, len, NULL);
831 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
834 SILC_GET32_MSB(mode, tmp);
836 /* Get created boolean value */
837 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
840 SILC_GET32_MSB(created, tmp);
841 if (created != 0 && created != 1)
844 /* Get channel key */
845 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
847 keyp = silc_buffer_alloc(len);
848 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
849 silc_buffer_put(keyp, tmp, len);
852 /* Parse the Channel ID */
853 id = silc_id_payload_parse_id(id_string, id_len, NULL);
858 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
860 if (!silc_hmac_alloc(tmp, NULL, &hmac))
864 /* Get the list count */
865 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
868 SILC_GET32_MSB(list_count, tmp);
870 /* Get Client ID list */
871 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
875 client_id_list = silc_buffer_alloc(len);
876 silc_buffer_pull_tail(client_id_list, len);
877 silc_buffer_put(client_id_list, tmp, len);
879 /* Get client mode list */
880 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
884 client_mode_list = silc_buffer_alloc(len);
885 silc_buffer_pull_tail(client_mode_list, len);
886 silc_buffer_put(client_mode_list, tmp, len);
888 /* Get founder key */
889 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
891 silc_pkcs_public_key_decode(tmp, len, &founder_key);
893 /* See whether we already have the channel. */
894 entry = silc_idlist_find_channel_by_name(server->local_list,
895 channel_name, &cache);
897 /* Add new channel */
899 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
900 (created == 0 ? "existing" : "created"), channel_name,
901 silc_id_render(id, SILC_ID_CHANNEL)));
903 /* If the channel is found from global list we must move it to the
905 entry = silc_idlist_find_channel_by_name(server->global_list,
906 channel_name, &cache);
908 silc_idlist_del_channel(server->global_list, entry);
910 /* Add the channel to our local list. */
911 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
912 SILC_CHANNEL_MODE_NONE, id,
913 server->router, NULL, hmac, 0);
918 server->stat.my_channels++;
919 server->stat.channels++;
921 /* The entry exists. */
923 /* If ID has changed, then update it to the cache too. */
924 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
925 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
927 entry->disabled = FALSE;
929 /* Remove the founder auth data if the mode is not set but we have
931 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
932 silc_pkcs_public_key_free(entry->founder_key);
933 entry->founder_key = NULL;
938 if (entry->founder_key)
939 silc_pkcs_public_key_free(entry->founder_key);
940 entry->founder_key = founder_key;
944 if (entry->hmac_name && hmac) {
945 silc_free(entry->hmac_name);
946 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
949 /* Get the ban list */
950 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
952 silc_free(entry->ban_list);
953 entry->ban_list = silc_memdup(tmp, len);
956 /* Get the invite list */
957 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
959 silc_free(entry->invite_list);
960 entry->invite_list = silc_memdup(tmp, len);
964 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
966 silc_free(entry->topic);
967 entry->topic = strdup(tmp);
970 /* If channel was not created we know there is global users on the
972 entry->global_users = (created == 0 ? TRUE : FALSE);
974 /* If channel was just created the mask must be zero */
975 if (!entry->global_users && mode) {
976 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
977 "new channel, forcing it to zero", cmd->sock->hostname));
981 /* Save channel mode */
984 /* Save channel key */
986 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
987 silc_server_save_channel_key(server, keyp, entry);
988 silc_buffer_free(keyp);
991 /* Save the users to the channel */
992 silc_server_save_users_on_channel(server, cmd->sock, entry,
993 client_id, client_id_list,
994 client_mode_list, list_count);
995 entry->users_resolved = TRUE;
998 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1000 silc_free(client_id);
1001 silc_server_command_reply_free(cmd);
1003 silc_pkcs_public_key_free(founder_key);
1005 silc_buffer_free(client_id_list);
1006 if (client_mode_list)
1007 silc_buffer_free(client_mode_list);
1010 /* Received reply to STATS command. */
1012 SILC_SERVER_CMD_REPLY_FUNC(stats)
1014 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1015 SilcServer server = cmd->server;
1016 SilcStatus status, error;
1019 SilcBufferStruct buf;
1021 COMMAND_CHECK_STATUS;
1023 /* Get statistics structure */
1024 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1025 if (server->server_type == SILC_SERVER && tmp) {
1026 silc_buffer_set(&buf, tmp, tmp_len);
1027 silc_buffer_unformat(&buf,
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(NULL),
1033 SILC_STR_UI_INT(NULL),
1034 SILC_STR_UI_INT(&server->stat.cell_clients),
1035 SILC_STR_UI_INT(&server->stat.cell_channels),
1036 SILC_STR_UI_INT(&server->stat.cell_servers),
1037 SILC_STR_UI_INT(&server->stat.clients),
1038 SILC_STR_UI_INT(&server->stat.channels),
1039 SILC_STR_UI_INT(&server->stat.servers),
1040 SILC_STR_UI_INT(&server->stat.routers),
1041 SILC_STR_UI_INT(&server->stat.server_ops),
1042 SILC_STR_UI_INT(&server->stat.router_ops),
1047 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1049 silc_server_command_reply_free(cmd);
1052 SILC_SERVER_CMD_REPLY_FUNC(users)
1054 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1055 SilcServer server = cmd->server;
1056 SilcStatus status, error;
1057 SilcChannelEntry channel;
1058 SilcChannelID *channel_id = NULL;
1059 SilcBuffer client_id_list;
1060 SilcBuffer client_mode_list;
1063 SilcUInt32 list_count;
1065 COMMAND_CHECK_STATUS;
1067 /* Get channel ID */
1068 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1071 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1075 /* Get channel entry */
1076 channel = silc_idlist_find_channel_by_id(server->local_list,
1079 channel = silc_idlist_find_channel_by_id(server->global_list,
1084 if (server->server_type != SILC_SERVER)
1087 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1088 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1089 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1090 1, 5, idp->data, idp->len);
1091 silc_buffer_free(idp);
1093 /* Register pending command callback. After we've received the channel
1094 information we will reprocess this command reply by re-calling this
1095 USERS command reply callback. */
1096 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1098 silc_server_command_reply_users, cmd);
1103 /* Get the list count */
1104 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1107 SILC_GET32_MSB(list_count, tmp);
1109 /* Get Client ID list */
1110 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1114 client_id_list = silc_buffer_alloc(tmp_len);
1115 silc_buffer_pull_tail(client_id_list, tmp_len);
1116 silc_buffer_put(client_id_list, tmp, tmp_len);
1118 /* Get client mode list */
1119 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1123 client_mode_list = silc_buffer_alloc(tmp_len);
1124 silc_buffer_pull_tail(client_mode_list, tmp_len);
1125 silc_buffer_put(client_mode_list, tmp, tmp_len);
1127 /* Save the users to the channel */
1128 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1129 client_id_list, client_mode_list,
1132 channel->global_users = silc_server_channel_has_global(channel);
1133 channel->users_resolved = TRUE;
1135 silc_buffer_free(client_id_list);
1136 silc_buffer_free(client_mode_list);
1139 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1140 silc_free(channel_id);
1142 silc_server_command_reply_free(cmd);
1145 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1147 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1148 SilcServer server = cmd->server;
1149 SilcStatus status, error;
1150 SilcClientEntry client = NULL;
1151 SilcServerEntry server_entry = NULL;
1152 SilcClientID *client_id = NULL;
1153 SilcServerID *server_id = NULL;
1155 unsigned char *tmp, *pk;
1158 SilcIDPayload idp = NULL;
1160 SilcPublicKey public_key = NULL;
1162 COMMAND_CHECK_STATUS;
1164 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1167 idp = silc_id_payload_parse(tmp, len);
1171 /* Get the public key payload */
1172 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1176 /* Decode the public key */
1178 SILC_GET16_MSB(pk_len, tmp);
1179 SILC_GET16_MSB(type, tmp + 2);
1182 if (type != SILC_SKE_PK_TYPE_SILC)
1185 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1188 id_type = silc_id_payload_get_type(idp);
1189 if (id_type == SILC_ID_CLIENT) {
1190 client_id = silc_id_payload_get_id(idp);
1192 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1195 client = silc_idlist_find_client_by_id(server->global_list,
1196 client_id, TRUE, NULL);
1201 client->data.public_key = public_key;
1203 } else if (id_type == SILC_ID_SERVER) {
1204 server_id = silc_id_payload_get_id(idp);
1206 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1208 if (!server_entry) {
1209 server_entry = silc_idlist_find_server_by_id(server->global_list,
1210 server_id, TRUE, NULL);
1215 server_entry->data.public_key = public_key;
1222 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1224 silc_id_payload_free(idp);
1225 silc_free(client_id);
1226 silc_free(server_id);
1228 silc_pkcs_public_key_free(public_key);
1230 silc_server_command_reply_free(cmd);
1233 SILC_SERVER_CMD_REPLY_FUNC(list)
1235 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1236 SilcServer server = cmd->server;
1237 SilcStatus status, error;
1238 SilcChannelID *channel_id = NULL;
1239 SilcChannelEntry channel;
1240 SilcIDCacheEntry cache;
1242 unsigned char *tmp, *name, *topic;
1243 SilcUInt32 usercount = 0;
1244 bool global_list = FALSE;
1246 COMMAND_CHECK_STATUS;
1248 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1249 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1253 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1254 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1255 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1257 SILC_GET32_MSB(usercount, tmp);
1259 /* Add the channel entry if we do not have it already */
1260 channel = silc_idlist_find_channel_by_name(server->local_list,
1263 channel = silc_idlist_find_channel_by_name(server->global_list,
1268 /* If router did not find such channel in its lists then this must
1269 be bogus channel or some router in the net is buggy. */
1270 if (server->server_type != SILC_SERVER)
1273 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1274 SILC_CHANNEL_MODE_NONE, channel_id,
1275 server->router, NULL, NULL,
1281 /* Found, update expiry */
1282 if (global_list && server->server_type == SILC_SERVER)
1283 cache->expire = time(NULL) + 60;
1286 channel->user_count = usercount;
1289 silc_free(channel->topic);
1290 channel->topic = strdup(topic);
1293 /* Pending callbacks are not executed if this was an list entry */
1294 if (status != SILC_STATUS_OK &&
1295 status != SILC_STATUS_LIST_END) {
1296 silc_server_command_reply_free(cmd);
1300 /* Now purge all old entries from the global list, otherwise we'll might
1301 have non-existent entries for long periods of time in the cache. */
1302 silc_idcache_purge(server->global_list->channels);
1305 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1306 silc_free(channel_id);
1308 silc_server_command_reply_free(cmd);
1311 SILC_SERVER_CMD_REPLY_FUNC(watch)
1313 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1314 SilcStatus status, error;
1316 COMMAND_CHECK_STATUS;
1319 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1321 silc_server_command_reply_free(cmd);