5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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 or the
27 COMMAND_CHECK_STATUS_LIST macros must have out: goto label. */
29 #define COMMAND_CHECK_STATUS \
31 SILC_LOG_DEBUG(("Start")); \
32 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); \
33 if (status != SILC_STATUS_OK) \
37 #define COMMAND_CHECK_STATUS_LIST \
39 SILC_LOG_DEBUG(("Start")); \
40 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); \
41 if (status != SILC_STATUS_OK && \
42 status != SILC_STATUS_LIST_START && \
43 status != SILC_STATUS_LIST_ITEM && \
44 status != SILC_STATUS_LIST_END) \
48 /* Server command reply list. Not all commands have reply function as
49 they are never sent by server. More maybe added later if need appears. */
50 SilcServerCommandReply silc_command_reply_list[] =
52 SILC_SERVER_CMD_REPLY(whois, WHOIS),
53 SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
54 SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
55 SILC_SERVER_CMD_REPLY(info, INFO),
56 SILC_SERVER_CMD_REPLY(motd, MOTD),
57 SILC_SERVER_CMD_REPLY(join, JOIN),
58 SILC_SERVER_CMD_REPLY(users, USERS),
59 SILC_SERVER_CMD_REPLY(getkey, GETKEY),
60 SILC_SERVER_CMD_REPLY(list, LIST),
65 /* Process received command reply. */
67 void silc_server_command_reply_process(SilcServer server,
68 SilcSocketConnection sock,
71 SilcServerCommandReply *cmd;
72 SilcServerCommandReplyContext ctx;
73 SilcCommandPayload payload;
77 SILC_LOG_DEBUG(("Start"));
79 /* Get command reply payload from packet */
80 payload = silc_command_payload_parse(buffer);
82 /* Silently ignore bad reply packet */
83 SILC_LOG_DEBUG(("Bad command reply packet"));
87 /* Allocate command reply context. This must be free'd by the
88 command reply routine receiving it. */
89 ctx = silc_calloc(1, sizeof(*ctx));
91 ctx->sock = silc_socket_dup(sock);
92 ctx->payload = payload;
93 ctx->args = silc_command_get_args(ctx->payload);
94 ident = silc_command_get_ident(ctx->payload);
96 /* Check for pending commands and mark to be exeucted */
98 silc_server_command_pending_check(server, ctx,
99 silc_command_get(ctx->payload),
100 ident, &ctx->callbacks_count);
102 /* Execute command reply */
103 command = silc_command_get(ctx->payload);
104 for (cmd = silc_command_reply_list; cmd->cb; cmd++)
105 if (cmd->cmd == command)
108 if (cmd == NULL || !cmd->cb) {
109 silc_server_command_reply_free(ctx);
116 /* Free command reply context and its internals. */
118 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
121 silc_command_payload_free(cmd->payload);
123 silc_socket_free(cmd->sock); /* Decrease the reference counter */
124 silc_free(cmd->callbacks);
129 /* Caches the received WHOIS information. */
132 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
134 SilcServer server = cmd->server;
135 unsigned char *tmp, *id_data;
136 char *nickname, *username, *realname, *servername = NULL;
137 SilcClientID *client_id;
138 SilcClientEntry client;
141 uint32 mode = 0, len, id_len;
143 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
144 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
145 username = silc_argument_get_arg_type(cmd->args, 4, &len);
146 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
147 if (!id_data || !nickname || !username || !realname) {
148 SILC_LOG_ERROR(("Incomplete WHOIS info: %s %s %s",
149 nickname ? nickname : "",
150 username ? username : "",
151 realname ? realname : ""));
155 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
157 SILC_GET32_MSB(mode, tmp);
159 client_id = silc_id_payload_parse_id(id_data, id_len);
163 /* Check if we have this client cached already. */
165 client = silc_idlist_find_client_by_id(server->local_list, client_id,
168 client = silc_idlist_find_client_by_id(server->global_list, client_id,
174 /* If router did not find such Client ID in its lists then this must
175 be bogus client or some router in the net is buggy. */
176 if (server->server_type != SILC_SERVER)
179 /* Take hostname out of nick string if it includes it. */
180 silc_parse_userfqdn(nickname, &nick, &servername);
182 /* We don't have that client anywhere, add it. The client is added
183 to global list since server didn't have it in the lists so it must be
185 client = silc_idlist_add_client(server->global_list, nick,
187 strdup(realname), client_id,
188 cmd->sock->user_data, NULL);
190 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
194 client->data.status |=
195 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
196 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
198 client->servername = servername;
200 /* We have the client already, update the data */
202 SILC_LOG_DEBUG(("Updating client data"));
204 /* Take hostname out of nick string if it includes it. */
205 silc_parse_userfqdn(nickname, &nick, &servername);
207 /* Remove the old cache entry */
208 silc_idcache_del_by_context(global ? server->global_list->clients :
209 server->local_list->clients, client);
211 silc_free(client->nickname);
212 silc_free(client->username);
213 silc_free(client->userinfo);
214 silc_free(client->servername);
216 client->nickname = nick;
217 client->username = strdup(username);
218 client->userinfo = strdup(realname);
219 client->servername = servername;
221 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
222 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
224 /* Create new cache entry */
225 silc_idcache_add(global ? server->global_list->clients :
226 server->local_list->clients, nick, client->id,
228 silc_free(client_id);
234 /* Reiceved reply for WHOIS command. We sent the whois request to our
235 primary router, if we are normal server, and thus has now received reply
236 to the command. We will figure out what client originally sent us the
237 command and will send the reply to it. If we are router we will figure
238 out who server sent us the command and send reply to that one. */
240 SILC_SERVER_CMD_REPLY_FUNC(whois)
242 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
243 SilcCommandStatus status;
245 COMMAND_CHECK_STATUS_LIST;
247 if (!silc_server_command_reply_whois_save(cmd))
250 /* Pending callbacks are not executed if this was an list entry */
251 if (status != SILC_STATUS_OK &&
252 status != SILC_STATUS_LIST_END) {
253 silc_server_command_reply_free(cmd);
258 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
259 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS);
260 silc_server_command_reply_free(cmd);
263 /* Caches the received WHOWAS information for a short period of time. */
266 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
268 SilcServer server = cmd->server;
270 unsigned char *id_data;
271 char *nickname, *username, *realname, *servername = NULL;
272 SilcClientID *client_id;
273 SilcClientEntry client;
274 SilcIDCacheEntry cache = NULL;
278 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
279 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
280 username = silc_argument_get_arg_type(cmd->args, 4, &len);
281 if (!id_data || !nickname || !username)
284 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
286 client_id = silc_id_payload_parse_id(id_data, id_len);
290 /* Check if we have this client cached already. */
292 client = silc_idlist_find_client_by_id(server->local_list, client_id,
295 client = silc_idlist_find_client_by_id(server->global_list,
296 client_id, FALSE, &cache);
301 /* If router did not find such Client ID in its lists then this must
302 be bogus client or some router in the net is buggy. */
303 if (server->server_type != SILC_SERVER)
306 /* Take hostname out of nick string if it includes it. */
307 silc_parse_userfqdn(nickname, &nick, &servername);
309 /* We don't have that client anywhere, add it. The client is added
310 to global list since server didn't have it in the lists so it must be
312 client = silc_idlist_add_client(server->global_list, nick,
313 strdup(username), strdup(realname),
314 silc_id_dup(client_id, SILC_ID_CLIENT),
315 cmd->sock->user_data, NULL);
317 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
321 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
322 client = silc_idlist_find_client_by_id(server->global_list,
323 client_id, TRUE, &cache);
324 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
325 client->servername = servername;
327 /* We have the client already, update the data */
329 /* Take hostname out of nick string if it includes it. */
330 silc_parse_userfqdn(nickname, &nick, &servername);
332 silc_free(client->nickname);
333 silc_free(client->username);
335 client->nickname = nick;
336 client->username = strdup(username);
337 client->servername = servername;
339 /* Remove the old cache entry and create a new one */
340 silc_idcache_del_by_context(global ? server->global_list->clients :
341 server->local_list->clients, client);
342 silc_idcache_add(global ? server->global_list->clients :
343 server->local_list->clients, nick, client->id,
347 silc_free(client_id);
352 /* Received reply for WHOWAS command. Cache the client information only for
353 a short period of time. */
355 SILC_SERVER_CMD_REPLY_FUNC(whowas)
357 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
358 SilcCommandStatus status;
360 COMMAND_CHECK_STATUS_LIST;
362 if (!silc_server_command_reply_whowas_save(cmd))
365 /* Pending callbacks are not executed if this was an list entry */
366 if (status != SILC_STATUS_OK &&
367 status != SILC_STATUS_LIST_END) {
368 silc_server_command_reply_free(cmd);
373 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
374 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOWAS);
375 silc_server_command_reply_free(cmd);
378 /* Caches the received IDENTIFY information. */
381 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
383 SilcServer server = cmd->server;
385 unsigned char *id_data;
387 SilcClientID *client_id = NULL;
388 SilcServerID *server_id = NULL;
389 SilcChannelID *channel_id = NULL;
390 SilcClientEntry client;
391 SilcServerEntry server_entry;
392 SilcChannelEntry channel;
395 SilcIDPayload idp = NULL;
398 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
401 idp = silc_id_payload_parse_data(id_data, id_len);
405 name = silc_argument_get_arg_type(cmd->args, 3, &len);
406 info = silc_argument_get_arg_type(cmd->args, 4, &len);
408 id_type = silc_id_payload_get_type(idp);
412 client_id = silc_id_payload_get_id(idp);
416 SILC_LOG_DEBUG(("Received client information"));
418 client = silc_idlist_find_client_by_id(server->local_list,
419 client_id, FALSE, NULL);
421 client = silc_idlist_find_client_by_id(server->global_list, client_id,
426 /* If router did not find such Client ID in its lists then this must
427 be bogus client or some router in the net is buggy. */
428 if (server->server_type != SILC_SERVER)
433 silc_parse_userfqdn(name, &nick, NULL);
435 /* We don't have that client anywhere, add it. The client is added
436 to global list since server didn't have it in the lists so it must be
438 client = silc_idlist_add_client(server->global_list, nick,
439 info ? strdup(info) : NULL, NULL,
440 client_id, cmd->sock->user_data, NULL);
442 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
445 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
446 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
447 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
449 /* We have the client already, update the data */
451 SILC_LOG_DEBUG(("Updating client data"));
455 silc_parse_userfqdn(name, &nick, NULL);
457 /* Remove the old cache entry */
458 silc_idcache_del_by_context(global ? server->global_list->clients :
459 server->local_list->clients, client);
461 silc_free(client->nickname);
462 client->nickname = nick;
466 silc_free(client->username);
467 client->username = strdup(info);
470 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
471 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
474 /* Add new cache entry */
475 silc_idcache_add(global ? server->global_list->clients :
476 server->local_list->clients, nick, client->id,
480 silc_free(client_id);
486 server_id = silc_id_payload_get_id(idp);
490 SILC_LOG_DEBUG(("Received server information"));
492 server_entry = silc_idlist_find_server_by_id(server->local_list,
493 server_id, FALSE, NULL);
495 server_entry = silc_idlist_find_server_by_id(server->global_list,
496 server_id, FALSE, NULL);
498 /* If router did not find such Server ID in its lists then this must
499 be bogus server or some router in the net is buggy. */
500 if (server->server_type != SILC_SERVER)
503 /* We don't have that server anywhere, add it. */
504 server_entry = silc_idlist_add_server(server->global_list,
506 server_id, NULL, NULL);
508 silc_free(server_id);
511 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
512 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
513 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
517 silc_free(server_id);
520 case SILC_ID_CHANNEL:
521 channel_id = silc_id_payload_get_id(idp);
525 SILC_LOG_DEBUG(("Received channel information"));
527 channel = silc_idlist_find_channel_by_id(server->local_list,
530 channel = silc_idlist_find_channel_by_id(server->global_list, channel_id,
533 /* If router did not find such Channel ID in its lists then this must
534 be bogus channel or some router in the net is buggy. */
535 if (server->server_type != SILC_SERVER)
538 /* We don't have that server anywhere, add it. */
539 channel = silc_idlist_add_channel(server->global_list, strdup(name),
540 SILC_CHANNEL_MODE_NONE, channel_id,
544 silc_free(channel_id);
550 silc_free(channel_id);
554 silc_id_payload_free(idp);
558 silc_id_payload_free(idp);
562 /* Received reply for forwarded IDENTIFY command. We have received the
563 requested identify information now and we will cache it. After this we
564 will call the pending command so that the requestee gets the information
567 SILC_SERVER_CMD_REPLY_FUNC(identify)
569 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
570 SilcCommandStatus status;
572 COMMAND_CHECK_STATUS_LIST;
574 if (!silc_server_command_reply_identify_save(cmd))
577 /* Pending callbacks are not executed if this was an list entry */
578 if (status != SILC_STATUS_OK &&
579 status != SILC_STATUS_LIST_END) {
580 silc_server_command_reply_free(cmd);
585 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
586 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_IDENTIFY);
587 silc_server_command_reply_free(cmd);
590 /* Received reply fro INFO command. Cache the server and its information */
592 SILC_SERVER_CMD_REPLY_FUNC(info)
594 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
595 SilcServer server = cmd->server;
596 SilcCommandStatus status;
597 SilcServerEntry entry;
598 SilcServerID *server_id;
600 unsigned char *tmp, *name;
602 COMMAND_CHECK_STATUS;
605 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
608 server_id = silc_id_payload_parse_id(tmp, tmp_len);
613 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
617 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
620 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
623 /* Add the server to global list */
624 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
625 entry = silc_idlist_add_server(server->global_list, name, 0,
626 server_id, NULL, NULL);
628 silc_free(server_id);
631 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
635 /* Get the info string */
636 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
640 entry->server_info = tmp ? strdup(tmp) : NULL;
643 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
644 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO);
645 silc_server_command_reply_free(cmd);
648 /* Received reply fro MOTD command. */
650 SILC_SERVER_CMD_REPLY_FUNC(motd)
652 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
653 SilcServer server = cmd->server;
654 SilcCommandStatus status;
655 SilcServerEntry entry = NULL;
656 SilcServerID *server_id;
660 COMMAND_CHECK_STATUS;
663 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
666 server_id = silc_id_payload_parse_id(tmp, tmp_len);
670 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
673 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
680 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
687 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
688 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_MOTD);
689 silc_server_command_reply_free(cmd);
695 /* Received reply for forwarded JOIN command. Router has created or joined
696 the client to the channel. We save some channel information locally
699 SILC_SERVER_CMD_REPLY_FUNC(join)
701 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
702 SilcServer server = cmd->server;
703 SilcIDCacheEntry cache = NULL;
704 SilcCommandStatus status;
706 SilcClientID *client_id = NULL;
707 SilcChannelEntry entry;
708 SilcHmac hmac = NULL;
709 uint32 id_len, len, list_count;
710 unsigned char *id_string;
711 char *channel_name, *tmp;
712 uint32 mode, created;
713 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
715 COMMAND_CHECK_STATUS;
717 /* Get channel name */
718 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
723 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
728 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
731 client_id = silc_id_payload_parse_id(tmp, len);
736 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
739 SILC_GET32_MSB(mode, tmp);
741 /* Get created boolean value */
742 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
745 SILC_GET32_MSB(created, tmp);
746 if (created != 0 && created != 1)
749 /* Get channel key */
750 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
752 keyp = silc_buffer_alloc(len);
753 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
754 silc_buffer_put(keyp, tmp, len);
757 id = silc_id_payload_parse_id(id_string, id_len);
762 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
764 if (!silc_hmac_alloc(tmp, NULL, &hmac))
768 /* Get the list count */
769 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
772 SILC_GET32_MSB(list_count, tmp);
774 /* Get Client ID list */
775 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
779 client_id_list = silc_buffer_alloc(len);
780 silc_buffer_pull_tail(client_id_list, len);
781 silc_buffer_put(client_id_list, tmp, len);
783 /* Get client mode list */
784 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
788 client_mode_list = silc_buffer_alloc(len);
789 silc_buffer_pull_tail(client_mode_list, len);
790 silc_buffer_put(client_mode_list, tmp, len);
792 /* See whether we already have the channel. */
793 entry = silc_idlist_find_channel_by_name(server->local_list,
794 channel_name, &cache);
796 /* Add new channel */
798 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
799 (created == 0 ? "existing" : "created"), channel_name,
800 silc_id_render(id, SILC_ID_CHANNEL)));
802 /* If the channel is found from global list we must move it to the
804 entry = silc_idlist_find_channel_by_name(server->global_list,
805 channel_name, &cache);
807 silc_idlist_del_channel(server->global_list, entry);
809 /* Add the channel to our local list. */
810 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
811 SILC_CHANNEL_MODE_NONE, id,
812 server->router, NULL, hmac);
817 server->stat.my_channels++;
819 /* The entry exists. */
820 silc_free(cache->id);
822 cache->id = entry->id;
823 entry->disabled = FALSE;
825 /* Remove the founder auth data if the mode is not set but we have
827 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
828 silc_pkcs_public_key_free(entry->founder_key);
829 if (entry->founder_passwd) {
830 silc_free(entry->founder_passwd);
831 entry->founder_passwd = NULL;
836 if (entry->hmac_name && hmac) {
837 silc_free(entry->hmac_name);
838 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
841 /* Get the ban list */
842 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
845 silc_free(entry->ban_list);
846 entry->ban_list = silc_calloc(len, sizeof(*entry->ban_list));
847 memcpy(entry->ban_list, tmp, len);
850 /* Get the invite list */
851 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
853 if (entry->invite_list)
854 silc_free(entry->invite_list);
855 entry->invite_list = silc_calloc(len, sizeof(*entry->invite_list));
856 memcpy(entry->invite_list, tmp, len);
860 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
863 silc_free(entry->topic);
864 entry->topic = strdup(tmp);
867 /* If channel was not created we know there is global users on the
869 entry->global_users = (created == 0 ? TRUE : FALSE);
871 /* If channel was just created the mask must be zero */
872 if (!entry->global_users && mode) {
873 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
874 "new channel, forcing it to zero", cmd->sock->hostname));
878 /* Save channel mode */
881 /* Save channel key */
882 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
883 silc_server_save_channel_key(server, keyp, entry);
885 silc_buffer_free(keyp);
887 /* Save the users to the channel */
888 silc_server_save_users_on_channel(server, cmd->sock, entry,
889 client_id, client_id_list,
890 client_mode_list, list_count);
893 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
894 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_JOIN);
895 silc_free(client_id);
896 silc_server_command_reply_free(cmd);
899 silc_buffer_free(client_id_list);
900 if (client_mode_list)
901 silc_buffer_free(client_mode_list);
904 SILC_SERVER_CMD_REPLY_FUNC(users)
906 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
907 SilcServer server = cmd->server;
908 SilcCommandStatus status;
909 SilcChannelEntry channel;
910 SilcChannelID *channel_id = NULL;
911 SilcBuffer client_id_list;
912 SilcBuffer client_mode_list;
917 COMMAND_CHECK_STATUS;
920 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
923 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
927 /* Get channel entry */
928 channel = silc_idlist_find_channel_by_id(server->local_list,
931 channel = silc_idlist_find_channel_by_id(server->global_list,
936 if (server->server_type != SILC_SERVER)
939 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
940 silc_server_send_command(server, server->router->connection,
941 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
942 1, 5, idp->data, idp->len);
943 silc_buffer_free(idp);
945 /* Register pending command callback. After we've received the channel
946 information we will reprocess this command reply by re-calling this
947 USERS command reply callback. */
948 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
950 NULL, silc_server_command_reply_users, cmd);
955 /* Get the list count */
956 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
959 SILC_GET32_MSB(list_count, tmp);
961 /* Get Client ID list */
962 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
966 client_id_list = silc_buffer_alloc(tmp_len);
967 silc_buffer_pull_tail(client_id_list, tmp_len);
968 silc_buffer_put(client_id_list, tmp, tmp_len);
970 /* Get client mode list */
971 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
975 client_mode_list = silc_buffer_alloc(tmp_len);
976 silc_buffer_pull_tail(client_mode_list, tmp_len);
977 silc_buffer_put(client_mode_list, tmp, tmp_len);
979 /* Save the users to the channel */
980 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
981 client_id_list, client_mode_list,
984 silc_buffer_free(client_id_list);
985 silc_buffer_free(client_mode_list);
988 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
989 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
990 silc_free(channel_id);
991 silc_server_command_reply_free(cmd);
994 SILC_SERVER_CMD_REPLY_FUNC(getkey)
996 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
997 SilcServer server = cmd->server;
998 SilcCommandStatus status;
999 SilcClientEntry client = NULL;
1000 SilcServerEntry server_entry = NULL;
1001 SilcClientID *client_id = NULL;
1002 SilcServerID *server_id = NULL;
1004 unsigned char *tmp, *pk;
1007 SilcIDPayload idp = NULL;
1009 SilcPublicKey public_key = NULL;
1011 COMMAND_CHECK_STATUS;
1013 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1016 idp = silc_id_payload_parse_data(tmp, len);
1020 /* Get the public key payload */
1021 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1025 /* Decode the public key */
1027 SILC_GET16_MSB(pk_len, tmp);
1028 SILC_GET16_MSB(type, tmp + 2);
1031 if (type != SILC_SKE_PK_TYPE_SILC)
1034 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1037 id_type = silc_id_payload_get_type(idp);
1038 if (id_type == SILC_ID_CLIENT) {
1039 client_id = silc_id_payload_get_id(idp);
1041 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1044 client = silc_idlist_find_client_by_id(server->global_list,
1045 client_id, TRUE, NULL);
1050 client->data.public_key = public_key;
1051 } else if (id_type == SILC_ID_SERVER) {
1052 server_id = silc_id_payload_get_id(idp);
1054 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1056 if (!server_entry) {
1057 server_entry = silc_idlist_find_server_by_id(server->global_list,
1058 server_id, TRUE, NULL);
1063 server_entry->data.public_key = public_key;
1069 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1070 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_GETKEY);
1072 silc_id_payload_free(idp);
1073 silc_free(client_id);
1074 silc_free(server_id);
1076 silc_pkcs_public_key_free(public_key);
1077 silc_server_command_reply_free(cmd);
1080 SILC_SERVER_CMD_REPLY_FUNC(list)
1082 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1083 SilcServer server = cmd->server;
1084 SilcCommandStatus status;
1085 SilcChannelID *channel_id = NULL;
1086 SilcChannelEntry channel;
1088 unsigned char *tmp, *name, *topic;
1089 uint32 usercount = 0;
1091 COMMAND_CHECK_STATUS_LIST;
1093 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1094 channel_id = silc_id_payload_parse_id(tmp, len);
1098 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1099 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1100 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1102 SILC_GET32_MSB(usercount, tmp);
1104 /* Add the channel entry if we do not have it already */
1105 channel = silc_idlist_find_channel_by_id(server->local_list,
1108 channel = silc_idlist_find_channel_by_id(server->global_list,
1111 /* If router did not find such Channel ID in its lists then this must
1112 be bogus channel or some router in the net is buggy. */
1113 if (server->server_type != SILC_SERVER)
1116 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1117 SILC_CHANNEL_MODE_NONE, channel_id,
1126 silc_free(channel->topic);
1127 channel->topic = strdup(topic);
1130 /* Pending callbacks are not executed if this was an list entry */
1131 if (status != SILC_STATUS_OK &&
1132 status != SILC_STATUS_LIST_END) {
1133 silc_server_command_reply_free(cmd);
1138 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1139 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_GETKEY);
1140 silc_free(channel_id);
1141 silc_server_command_reply_free(cmd);