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,
216 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
220 client->data.status |=
221 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
222 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
224 client->servername = servername;
226 /* We have the client already, update the data */
228 SILC_LOG_DEBUG(("Updating client data"));
230 /* Take hostname out of nick string if it includes it. */
231 silc_parse_userfqdn(nickname, &nick, &servername);
233 /* Remove the old cache entry */
234 silc_idcache_del_by_context(global ? server->global_list->clients :
235 server->local_list->clients, client);
237 silc_free(client->nickname);
238 silc_free(client->username);
239 silc_free(client->userinfo);
240 silc_free(client->servername);
242 client->nickname = nick;
243 client->username = strdup(username);
244 client->userinfo = strdup(realname);
245 client->servername = servername;
247 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
248 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
250 /* Create new cache entry */
251 silc_idcache_add(global ? server->global_list->clients :
252 server->local_list->clients, nick, client->id,
254 silc_free(client_id);
257 /* Save channel list if it was sent to us */
258 if (server->server_type == SILC_SERVER) {
259 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
260 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
262 SilcBufferStruct channels_buf, umodes_buf;
263 silc_buffer_set(&channels_buf, tmp, len);
264 silc_buffer_set(&umodes_buf, umodes, len2);
265 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
268 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
272 /* If client is global and is not on any channel then add that we'll
273 expire the entry after a while. */
274 if (global && !silc_hash_table_count(client->channels))
275 cache->expire = time(NULL) + 300;
278 if (fingerprint && flen == sizeof(client->data.fingerprint))
279 memcpy(client->data.fingerprint, fingerprint, flen);
284 /* Reiceved reply for WHOIS command. We sent the whois request to our
285 primary router, if we are normal server, and thus has now received reply
286 to the command. We will figure out what client originally sent us the
287 command and will send the reply to it. If we are router we will figure
288 out who server sent us the command and send reply to that one. */
290 SILC_SERVER_CMD_REPLY_FUNC(whois)
292 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
293 SilcStatus status, error;
295 COMMAND_CHECK_STATUS;
297 if (!silc_server_command_reply_whois_save(cmd))
300 /* Pending callbacks are not executed if this was an list entry */
301 if (status != SILC_STATUS_OK &&
302 status != SILC_STATUS_LIST_END) {
303 silc_server_command_reply_free(cmd);
308 silc_server_command_process_error(cmd, error);
309 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
310 silc_server_command_reply_free(cmd);
314 silc_server_command_process_error(cmd, error);
315 silc_server_command_reply_free(cmd);
318 /* Caches the received WHOWAS information for a short period of time. */
321 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
323 SilcServer server = cmd->server;
324 SilcUInt32 len, id_len;
325 unsigned char *id_data;
326 char *nickname, *username, *realname, *servername = NULL;
327 SilcClientID *client_id;
328 SilcClientEntry client;
329 SilcIDCacheEntry cache = NULL;
333 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
334 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
335 username = silc_argument_get_arg_type(cmd->args, 4, &len);
336 if (!id_data || !nickname || !username)
339 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
341 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
345 /* Check if we have this client cached already. */
347 client = silc_idlist_find_client_by_id(server->local_list, client_id,
350 client = silc_idlist_find_client_by_id(server->global_list,
351 client_id, FALSE, &cache);
356 /* If router did not find such Client ID in its lists then this must
357 be bogus client or some router in the net is buggy. */
358 if (server->server_type != SILC_SERVER)
361 /* Take hostname out of nick string if it includes it. */
362 silc_parse_userfqdn(nickname, &nick, &servername);
364 /* We don't have that client anywhere, add it. The client is added
365 to global list since server didn't have it in the lists so it must be
367 client = silc_idlist_add_client(server->global_list, nick,
368 strdup(username), strdup(realname),
369 silc_id_dup(client_id, SILC_ID_CLIENT),
370 cmd->sock->user_data, NULL,
371 SILC_ID_CACHE_EXPIRE_DEF);
373 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
377 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
378 client->servername = servername;
380 /* We have the client already, update the data */
382 /* Take hostname out of nick string if it includes it. */
383 silc_parse_userfqdn(nickname, &nick, &servername);
385 silc_free(client->nickname);
386 silc_free(client->username);
388 client->nickname = nick;
389 client->username = strdup(username);
390 client->servername = servername;
392 /* Remove the old cache entry and create a new one */
393 silc_idcache_del_by_context(global ? server->global_list->clients :
394 server->local_list->clients, client);
395 silc_idcache_add(global ? server->global_list->clients :
396 server->local_list->clients, nick, client->id,
400 silc_free(client_id);
405 /* Received reply for WHOWAS command. Cache the client information only for
406 a short period of time. */
408 SILC_SERVER_CMD_REPLY_FUNC(whowas)
410 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
411 SilcStatus status, error;
413 COMMAND_CHECK_STATUS;
415 if (!silc_server_command_reply_whowas_save(cmd))
418 /* Pending callbacks are not executed if this was an list entry */
419 if (status != SILC_STATUS_OK &&
420 status != SILC_STATUS_LIST_END) {
421 silc_server_command_reply_free(cmd);
426 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
428 silc_server_command_reply_free(cmd);
431 /* Caches the received IDENTIFY information. */
434 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
436 SilcServer server = cmd->server;
437 SilcUInt32 len, id_len;
438 unsigned char *id_data;
440 SilcClientID *client_id = NULL;
441 SilcServerID *server_id = NULL;
442 SilcChannelID *channel_id = NULL;
443 SilcClientEntry client;
444 SilcServerEntry server_entry;
445 SilcChannelEntry channel;
448 SilcIDPayload idp = NULL;
452 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
455 idp = silc_id_payload_parse(id_data, id_len);
459 name = silc_argument_get_arg_type(cmd->args, 3, &len);
460 info = silc_argument_get_arg_type(cmd->args, 4, &len);
462 id_type = silc_id_payload_get_type(idp);
466 client_id = silc_id_payload_get_id(idp);
470 SILC_LOG_DEBUG(("Received client information"));
472 client = silc_idlist_find_client_by_id(server->local_list,
473 client_id, FALSE, NULL);
475 client = silc_idlist_find_client_by_id(server->global_list, client_id,
480 /* If router did not find such Client ID in its lists then this must
481 be bogus client or some router in the net is buggy. */
482 if (server->server_type != SILC_SERVER)
487 silc_parse_userfqdn(name, &nick, NULL);
489 /* We don't have that client anywhere, add it. The client is added
490 to global list since server didn't have it in the lists so it must be
492 client = silc_idlist_add_client(server->global_list, nick,
493 info ? strdup(info) : NULL, NULL,
494 client_id, cmd->sock->user_data, NULL,
497 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
500 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
501 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
502 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
504 /* We have the client already, update the data */
506 SILC_LOG_DEBUG(("Updating client data"));
510 silc_parse_userfqdn(name, &nick, NULL);
512 /* Remove the old cache entry */
513 silc_idcache_del_by_context(global ? server->global_list->clients :
514 server->local_list->clients, client);
516 silc_free(client->nickname);
517 client->nickname = nick;
521 silc_free(client->username);
522 client->username = strdup(info);
525 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
526 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
529 /* If client is global and is not on any channel then add that we'll
530 expire the entry after a while. */
531 if (global && !silc_hash_table_count(client->channels) &&
532 server->server_type == SILC_SERVER)
533 expire = time(NULL) + 300;
535 /* Add new cache entry */
536 silc_idcache_add(global ? server->global_list->clients :
537 server->local_list->clients, nick, client->id,
538 client, expire, NULL);
541 silc_free(client_id);
550 server_id = silc_id_payload_get_id(idp);
554 SILC_LOG_DEBUG(("Received server information"));
556 server_entry = silc_idlist_find_server_by_id(server->local_list,
557 server_id, FALSE, NULL);
559 server_entry = silc_idlist_find_server_by_id(server->global_list,
560 server_id, FALSE, NULL);
562 /* If router did not find such Server ID in its lists then this must
563 be bogus server or some router in the net is buggy. */
564 if (server->server_type != SILC_SERVER)
567 /* We don't have that server anywhere, add it. */
568 server_entry = silc_idlist_add_server(server->global_list,
570 server_id, server->router,
571 SILC_PRIMARY_ROUTE(server));
573 silc_free(server_id);
576 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
577 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
578 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
582 silc_free(server_id);
585 case SILC_ID_CHANNEL:
589 channel_id = silc_id_payload_get_id(idp);
593 SILC_LOG_DEBUG(("Received channel information"));
595 channel = silc_idlist_find_channel_by_name(server->local_list,
598 channel = silc_idlist_find_channel_by_name(server->global_list,
601 /* If router did not find such Channel ID in its lists then this must
602 be bogus channel or some router in the net is buggy. */
603 if (server->server_type != SILC_SERVER)
606 /* We don't have that channel anywhere, add it. */
607 channel = silc_idlist_add_channel(server->global_list, strdup(name),
608 SILC_CHANNEL_MODE_NONE, channel_id,
609 server->router, NULL, NULL, 0);
611 silc_free(channel_id);
617 silc_free(channel_id);
621 silc_id_payload_free(idp);
625 silc_id_payload_free(idp);
629 /* Received reply for forwarded IDENTIFY command. We have received the
630 requested identify information now and we will cache it. After this we
631 will call the pending command so that the requestee gets the information
634 SILC_SERVER_CMD_REPLY_FUNC(identify)
636 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
637 SilcStatus status, error;
639 COMMAND_CHECK_STATUS;
641 if (!silc_server_command_reply_identify_save(cmd))
644 /* Pending callbacks are not executed if this was an list entry */
645 if (status != SILC_STATUS_OK &&
646 status != SILC_STATUS_LIST_END) {
647 silc_server_command_reply_free(cmd);
652 silc_server_command_process_error(cmd, error);
653 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
654 silc_server_command_reply_free(cmd);
658 silc_server_command_process_error(cmd, error);
659 silc_server_command_reply_free(cmd);
662 /* Received reply fro INFO command. Cache the server and its information */
664 SILC_SERVER_CMD_REPLY_FUNC(info)
666 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
667 SilcServer server = cmd->server;
668 SilcStatus status, error;
669 SilcServerEntry entry;
670 SilcServerID *server_id;
672 unsigned char *tmp, *name;
674 COMMAND_CHECK_STATUS;
677 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
680 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
685 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
689 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
692 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
695 /* Add the server to global list */
696 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
697 entry = silc_idlist_add_server(server->global_list, name, 0,
698 server_id, cmd->sock->user_data,
701 silc_free(server_id);
704 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
708 /* Get the info string */
709 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
713 entry->server_info = tmp ? strdup(tmp) : NULL;
716 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
718 silc_server_command_reply_free(cmd);
721 /* Received reply fro MOTD command. */
723 SILC_SERVER_CMD_REPLY_FUNC(motd)
725 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
726 SilcServer server = cmd->server;
727 SilcStatus status, error;
728 SilcServerEntry entry = NULL;
729 SilcServerID *server_id;
733 COMMAND_CHECK_STATUS;
736 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
739 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
743 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
746 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
753 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
760 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
762 silc_server_command_reply_free(cmd);
768 /* Received reply for forwarded JOIN command. Router has created or joined
769 the client to the channel. We save some channel information locally
772 SILC_SERVER_CMD_REPLY_FUNC(join)
774 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
775 SilcServer server = cmd->server;
776 SilcIDCacheEntry cache = NULL;
777 SilcStatus status, error;
779 SilcClientID *client_id = NULL;
780 SilcChannelEntry entry;
781 SilcHmac hmac = NULL;
782 SilcUInt32 id_len, len, list_count;
783 unsigned char *id_string;
784 char *channel_name, *tmp;
785 SilcUInt32 mode, created;
786 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
787 SilcPublicKey founder_key = NULL;
789 COMMAND_CHECK_STATUS;
791 /* Get channel name */
792 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
797 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
802 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
805 client_id = silc_id_payload_parse_id(tmp, len, NULL);
810 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
813 SILC_GET32_MSB(mode, tmp);
815 /* Get created boolean value */
816 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
819 SILC_GET32_MSB(created, tmp);
820 if (created != 0 && created != 1)
823 /* Get channel key */
824 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
826 keyp = silc_buffer_alloc(len);
827 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
828 silc_buffer_put(keyp, tmp, len);
831 /* Parse the Channel ID */
832 id = silc_id_payload_parse_id(id_string, id_len, NULL);
837 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
839 if (!silc_hmac_alloc(tmp, NULL, &hmac))
843 /* Get the list count */
844 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
847 SILC_GET32_MSB(list_count, tmp);
849 /* Get Client ID list */
850 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
854 client_id_list = silc_buffer_alloc(len);
855 silc_buffer_pull_tail(client_id_list, len);
856 silc_buffer_put(client_id_list, tmp, len);
858 /* Get client mode list */
859 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
863 client_mode_list = silc_buffer_alloc(len);
864 silc_buffer_pull_tail(client_mode_list, len);
865 silc_buffer_put(client_mode_list, tmp, len);
867 /* Get founder key */
868 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
870 silc_pkcs_public_key_decode(tmp, len, &founder_key);
872 /* See whether we already have the channel. */
873 entry = silc_idlist_find_channel_by_name(server->local_list,
874 channel_name, &cache);
876 /* Add new channel */
878 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
879 (created == 0 ? "existing" : "created"), channel_name,
880 silc_id_render(id, SILC_ID_CHANNEL)));
882 /* If the channel is found from global list we must move it to the
884 entry = silc_idlist_find_channel_by_name(server->global_list,
885 channel_name, &cache);
887 silc_idlist_del_channel(server->global_list, entry);
889 /* Add the channel to our local list. */
890 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
891 SILC_CHANNEL_MODE_NONE, id,
892 server->router, NULL, hmac, 0);
897 server->stat.my_channels++;
898 server->stat.channels++;
900 /* The entry exists. */
902 /* If ID has changed, then update it to the cache too. */
903 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
904 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
906 entry->disabled = FALSE;
908 /* Remove the founder auth data if the mode is not set but we have
910 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
911 silc_pkcs_public_key_free(entry->founder_key);
912 entry->founder_key = NULL;
917 if (entry->founder_key)
918 silc_pkcs_public_key_free(entry->founder_key);
919 entry->founder_key = founder_key;
923 if (entry->hmac_name && hmac) {
924 silc_free(entry->hmac_name);
925 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
928 /* Get the ban list */
929 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
931 silc_free(entry->ban_list);
932 entry->ban_list = silc_memdup(tmp, len);
935 /* Get the invite list */
936 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
938 silc_free(entry->invite_list);
939 entry->invite_list = silc_memdup(tmp, len);
943 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
945 silc_free(entry->topic);
946 entry->topic = strdup(tmp);
949 /* If channel was not created we know there is global users on the
951 entry->global_users = (created == 0 ? TRUE : FALSE);
953 /* If channel was just created the mask must be zero */
954 if (!entry->global_users && mode) {
955 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
956 "new channel, forcing it to zero", cmd->sock->hostname));
960 /* Save channel mode */
963 /* Save channel key */
965 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
966 silc_server_save_channel_key(server, keyp, entry);
967 silc_buffer_free(keyp);
970 /* Save the users to the channel */
971 silc_server_save_users_on_channel(server, cmd->sock, entry,
972 client_id, client_id_list,
973 client_mode_list, list_count);
974 entry->users_resolved = TRUE;
977 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
979 silc_free(client_id);
980 silc_server_command_reply_free(cmd);
982 silc_pkcs_public_key_free(founder_key);
984 silc_buffer_free(client_id_list);
985 if (client_mode_list)
986 silc_buffer_free(client_mode_list);
989 /* Received reply to STATS command. */
991 SILC_SERVER_CMD_REPLY_FUNC(stats)
993 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
994 SilcServer server = cmd->server;
995 SilcStatus status, error;
998 SilcBufferStruct buf;
1000 COMMAND_CHECK_STATUS;
1002 /* Get statistics structure */
1003 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1004 if (server->server_type == SILC_SERVER && tmp) {
1005 silc_buffer_set(&buf, tmp, tmp_len);
1006 silc_buffer_unformat(&buf,
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(NULL),
1013 SILC_STR_UI_INT(&server->stat.cell_clients),
1014 SILC_STR_UI_INT(&server->stat.cell_channels),
1015 SILC_STR_UI_INT(&server->stat.cell_servers),
1016 SILC_STR_UI_INT(&server->stat.clients),
1017 SILC_STR_UI_INT(&server->stat.channels),
1018 SILC_STR_UI_INT(&server->stat.servers),
1019 SILC_STR_UI_INT(&server->stat.routers),
1020 SILC_STR_UI_INT(&server->stat.server_ops),
1021 SILC_STR_UI_INT(&server->stat.router_ops),
1026 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1028 silc_server_command_reply_free(cmd);
1031 SILC_SERVER_CMD_REPLY_FUNC(users)
1033 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1034 SilcServer server = cmd->server;
1035 SilcStatus status, error;
1036 SilcChannelEntry channel;
1037 SilcChannelID *channel_id = NULL;
1038 SilcBuffer client_id_list;
1039 SilcBuffer client_mode_list;
1042 SilcUInt32 list_count;
1044 COMMAND_CHECK_STATUS;
1046 /* Get channel ID */
1047 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1050 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1054 /* Get channel entry */
1055 channel = silc_idlist_find_channel_by_id(server->local_list,
1058 channel = silc_idlist_find_channel_by_id(server->global_list,
1063 if (server->server_type != SILC_SERVER)
1066 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1067 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1068 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1069 1, 5, idp->data, idp->len);
1070 silc_buffer_free(idp);
1072 /* Register pending command callback. After we've received the channel
1073 information we will reprocess this command reply by re-calling this
1074 USERS command reply callback. */
1075 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1077 silc_server_command_reply_users, cmd);
1082 /* Get the list count */
1083 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1086 SILC_GET32_MSB(list_count, tmp);
1088 /* Get Client ID list */
1089 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1093 client_id_list = silc_buffer_alloc(tmp_len);
1094 silc_buffer_pull_tail(client_id_list, tmp_len);
1095 silc_buffer_put(client_id_list, tmp, tmp_len);
1097 /* Get client mode list */
1098 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1102 client_mode_list = silc_buffer_alloc(tmp_len);
1103 silc_buffer_pull_tail(client_mode_list, tmp_len);
1104 silc_buffer_put(client_mode_list, tmp, tmp_len);
1106 /* Save the users to the channel */
1107 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1108 client_id_list, client_mode_list,
1111 channel->global_users = silc_server_channel_has_global(channel);
1112 channel->users_resolved = TRUE;
1114 silc_buffer_free(client_id_list);
1115 silc_buffer_free(client_mode_list);
1118 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1119 silc_free(channel_id);
1121 silc_server_command_reply_free(cmd);
1124 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1126 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1127 SilcServer server = cmd->server;
1128 SilcStatus status, error;
1129 SilcClientEntry client = NULL;
1130 SilcServerEntry server_entry = NULL;
1131 SilcClientID *client_id = NULL;
1132 SilcServerID *server_id = NULL;
1134 unsigned char *tmp, *pk;
1137 SilcIDPayload idp = NULL;
1139 SilcPublicKey public_key = NULL;
1141 COMMAND_CHECK_STATUS;
1143 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1146 idp = silc_id_payload_parse(tmp, len);
1150 /* Get the public key payload */
1151 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1155 /* Decode the public key */
1157 SILC_GET16_MSB(pk_len, tmp);
1158 SILC_GET16_MSB(type, tmp + 2);
1161 if (type != SILC_SKE_PK_TYPE_SILC)
1164 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1167 id_type = silc_id_payload_get_type(idp);
1168 if (id_type == SILC_ID_CLIENT) {
1169 client_id = silc_id_payload_get_id(idp);
1171 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1174 client = silc_idlist_find_client_by_id(server->global_list,
1175 client_id, TRUE, NULL);
1180 client->data.public_key = public_key;
1182 } else if (id_type == SILC_ID_SERVER) {
1183 server_id = silc_id_payload_get_id(idp);
1185 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1187 if (!server_entry) {
1188 server_entry = silc_idlist_find_server_by_id(server->global_list,
1189 server_id, TRUE, NULL);
1194 server_entry->data.public_key = public_key;
1201 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1203 silc_id_payload_free(idp);
1204 silc_free(client_id);
1205 silc_free(server_id);
1207 silc_pkcs_public_key_free(public_key);
1209 silc_server_command_reply_free(cmd);
1212 SILC_SERVER_CMD_REPLY_FUNC(list)
1214 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1215 SilcServer server = cmd->server;
1216 SilcStatus status, error;
1217 SilcChannelID *channel_id = NULL;
1218 SilcChannelEntry channel;
1219 SilcIDCacheEntry cache;
1221 unsigned char *tmp, *name, *topic;
1222 SilcUInt32 usercount = 0;
1223 bool global_list = FALSE;
1225 COMMAND_CHECK_STATUS;
1227 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1228 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1232 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1233 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1234 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1236 SILC_GET32_MSB(usercount, tmp);
1238 /* Add the channel entry if we do not have it already */
1239 channel = silc_idlist_find_channel_by_name(server->local_list,
1242 channel = silc_idlist_find_channel_by_name(server->global_list,
1247 /* If router did not find such channel in its lists then this must
1248 be bogus channel or some router in the net is buggy. */
1249 if (server->server_type != SILC_SERVER)
1252 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1253 SILC_CHANNEL_MODE_NONE, channel_id,
1254 server->router, NULL, NULL,
1260 /* Found, update expiry */
1261 if (global_list && server->server_type == SILC_SERVER)
1262 cache->expire = time(NULL) + 60;
1265 channel->user_count = usercount;
1268 silc_free(channel->topic);
1269 channel->topic = strdup(topic);
1272 /* Pending callbacks are not executed if this was an list entry */
1273 if (status != SILC_STATUS_OK &&
1274 status != SILC_STATUS_LIST_END) {
1275 silc_server_command_reply_free(cmd);
1279 /* Now purge all old entries from the global list, otherwise we'll might
1280 have non-existent entries for long periods of time in the cache. */
1281 silc_idcache_purge(server->global_list->channels);
1284 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1285 silc_free(channel_id);
1287 silc_server_command_reply_free(cmd);
1290 SILC_SERVER_CMD_REPLY_FUNC(watch)
1292 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1293 SilcStatus status, error;
1295 COMMAND_CHECK_STATUS;
1298 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1300 silc_server_command_reply_free(cmd);