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),
64 /* Process received command reply. */
66 void silc_server_command_reply_process(SilcServer server,
67 SilcSocketConnection sock,
70 SilcServerCommandReply *cmd;
71 SilcServerCommandReplyContext ctx;
72 SilcCommandPayload payload;
76 SILC_LOG_DEBUG(("Start"));
78 /* Get command reply payload from packet */
79 payload = silc_command_payload_parse(buffer);
81 /* Silently ignore bad reply packet */
82 SILC_LOG_DEBUG(("Bad command reply packet"));
86 /* Allocate command reply context. This must be free'd by the
87 command reply routine receiving it. */
88 ctx = silc_calloc(1, sizeof(*ctx));
90 ctx->sock = silc_socket_dup(sock);
91 ctx->payload = payload;
92 ctx->args = silc_command_get_args(ctx->payload);
93 ident = silc_command_get_ident(ctx->payload);
95 /* Check for pending commands and mark to be exeucted */
96 silc_server_command_pending_check(server, ctx,
97 silc_command_get(ctx->payload), ident);
99 /* Execute command reply */
100 command = silc_command_get(ctx->payload);
101 for (cmd = silc_command_reply_list; cmd->cb; cmd++)
102 if (cmd->cmd == command)
105 if (cmd == NULL || !cmd->cb) {
106 silc_server_command_reply_free(ctx);
113 /* Free command reply context and its internals. */
115 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
118 silc_command_payload_free(cmd->payload);
120 silc_socket_free(cmd->sock); /* Decrease the reference counter */
125 /* Caches the received WHOIS information. */
128 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
130 SilcServer server = cmd->server;
131 unsigned char *tmp, *id_data;
132 char *nickname, *username, *realname, *servername = NULL;
133 SilcClientID *client_id;
134 SilcClientEntry client;
137 uint32 mode = 0, len, id_len;
139 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
140 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
141 username = silc_argument_get_arg_type(cmd->args, 4, &len);
142 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
143 if (!id_data || !nickname || !username || !realname) {
144 SILC_LOG_ERROR(("Incomplete WHOIS info: %s %s %s",
145 nickname ? nickname : "",
146 username ? username : "",
147 realname ? realname : ""));
151 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
153 SILC_GET32_MSB(mode, tmp);
155 client_id = silc_id_payload_parse_id(id_data, id_len);
159 /* Check if we have this client cached already. */
161 client = silc_idlist_find_client_by_id(server->local_list, client_id,
164 client = silc_idlist_find_client_by_id(server->global_list, client_id,
170 /* If router did not find such Client ID in its lists then this must
171 be bogus client or some router in the net is buggy. */
172 if (server->server_type == SILC_ROUTER)
175 /* Take hostname out of nick string if it includes it. */
176 if (strchr(nickname, '@')) {
177 int len = strcspn(nickname, "@");
178 nick = silc_calloc(len + 1, sizeof(char));
179 servername = silc_calloc((strlen(nickname) - len) + 1, sizeof(char));
180 memcpy(nick, nickname, len);
181 memcpy(servername, nickname + len + 1, strlen(nickname) - len);
183 nick = strdup(nickname);
186 /* We don't have that client anywhere, add it. The client is added
187 to global list since server didn't have it in the lists so it must be
189 client = silc_idlist_add_client(server->global_list, nick,
191 strdup(realname), client_id,
192 cmd->sock->user_data, NULL);
194 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
198 client->data.registered = TRUE;
200 client->servername = servername;
202 /* We have the client already, update the data */
204 SILC_LOG_DEBUG(("Updating client data"));
206 /* Take hostname out of nick string if it includes it. */
207 if (strchr(nickname, '@')) {
208 int len = strcspn(nickname, "@");
209 nick = silc_calloc(len + 1, sizeof(char));
210 servername = silc_calloc((strlen(nickname) - len) + 1, sizeof(char));
211 memcpy(nick, nickname, len);
212 memcpy(servername, nickname + len + 1, strlen(nickname) - len);
214 nick = strdup(nickname);
217 if (client->nickname)
218 silc_free(client->nickname);
219 if (client->username)
220 silc_free(client->username);
221 if (client->userinfo)
222 silc_free(client->userinfo);
224 client->nickname = nick;
225 client->username = strdup(username);
226 client->userinfo = strdup(realname);
228 client->servername = servername;
230 /* Remove the old cache entry and create a new one */
231 silc_idcache_del_by_context(global ? server->global_list->clients :
232 server->local_list->clients, client);
233 silc_idcache_add(global ? server->global_list->clients :
234 server->local_list->clients, nick, client->id,
236 silc_free(client_id);
242 /* Reiceved reply for WHOIS command. We sent the whois request to our
243 primary router, if we are normal server, and thus has now received reply
244 to the command. We will figure out what client originally sent us the
245 command and will send the reply to it. If we are router we will figure
246 out who server sent us the command and send reply to that one. */
248 SILC_SERVER_CMD_REPLY_FUNC(whois)
250 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
251 SilcCommandStatus status;
253 COMMAND_CHECK_STATUS_LIST;
255 if (!silc_server_command_reply_whois_save(cmd))
258 /* Pending callbacks are not executed if this was an list entry */
259 if (status != SILC_STATUS_OK &&
260 status != SILC_STATUS_LIST_END) {
261 silc_server_command_reply_free(cmd);
266 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
267 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS);
268 silc_server_command_reply_free(cmd);
271 /* Caches the received WHOWAS information for a short period of time. */
274 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
276 SilcServer server = cmd->server;
278 unsigned char *id_data;
279 char *nickname, *username, *realname, *servername = NULL;
280 SilcClientID *client_id;
281 SilcClientEntry client;
282 SilcIDCacheEntry cache = NULL;
286 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
287 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
288 username = silc_argument_get_arg_type(cmd->args, 4, &len);
289 if (!id_data || !nickname || !username)
292 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
294 client_id = silc_id_payload_parse_id(id_data, id_len);
298 /* Check if we have this client cached already. */
300 client = silc_idlist_find_client_by_id(server->local_list, client_id,
303 client = silc_idlist_find_client_by_id(server->global_list,
304 client_id, FALSE, &cache);
309 /* If router did not find such Client ID in its lists then this must
310 be bogus client or some router in the net is buggy. */
311 if (server->server_type == SILC_ROUTER)
314 /* Take hostname out of nick string if it includes it. */
315 if (strchr(nickname, '@')) {
316 int len = strcspn(nickname, "@");
317 nick = silc_calloc(len + 1, sizeof(char));
318 servername = silc_calloc((strlen(nickname) - len) + 1, sizeof(char));
319 memcpy(nick, nickname, len);
320 memcpy(servername, nickname + len + 1, strlen(nickname) - len);
322 nick = strdup(nickname);
325 /* We don't have that client anywhere, add it. The client is added
326 to global list since server didn't have it in the lists so it must be
328 client = silc_idlist_add_client(server->global_list, nick,
329 strdup(username), strdup(realname),
330 silc_id_dup(client_id, SILC_ID_CLIENT),
331 cmd->sock->user_data, NULL);
333 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
337 client->data.registered = FALSE;
338 client = silc_idlist_find_client_by_id(server->global_list,
339 client_id, TRUE, &cache);
340 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
341 client->servername = servername;
343 /* We have the client already, update the data */
345 /* Take hostname out of nick string if it includes it. */
346 if (strchr(nickname, '@')) {
347 int len = strcspn(nickname, "@");
348 nick = silc_calloc(len + 1, sizeof(char));
349 servername = silc_calloc((strlen(nickname) - len) + 1, sizeof(char));
350 memcpy(nick, nickname, len);
351 memcpy(servername, nickname + len + 1, strlen(nickname) - len);
353 nick = strdup(nickname);
356 if (client->nickname)
357 silc_free(client->nickname);
358 if (client->username)
359 silc_free(client->username);
361 client->nickname = nick;
362 client->username = strdup(username);
363 client->servername = servername;
365 /* Remove the old cache entry and create a new one */
366 silc_idcache_del_by_context(global ? server->global_list->clients :
367 server->local_list->clients, client);
368 silc_idcache_add(global ? server->global_list->clients :
369 server->local_list->clients, nick, client->id,
373 silc_free(client_id);
378 /* Received reply for WHOWAS command. Cache the client information only for
379 a short period of time. */
381 SILC_SERVER_CMD_REPLY_FUNC(whowas)
383 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
384 SilcCommandStatus status;
386 COMMAND_CHECK_STATUS_LIST;
388 if (!silc_server_command_reply_whowas_save(cmd))
391 /* Pending callbacks are not executed if this was an list entry */
392 if (status != SILC_STATUS_OK &&
393 status != SILC_STATUS_LIST_END) {
394 silc_server_command_reply_free(cmd);
399 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
400 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOWAS);
401 silc_server_command_reply_free(cmd);
404 /* Caches the received IDENTIFY information. */
407 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
409 SilcServer server = cmd->server;
411 unsigned char *id_data;
413 SilcClientID *client_id = NULL;
414 SilcServerID *server_id = NULL;
415 SilcChannelID *channel_id = NULL;
416 SilcClientEntry client;
417 SilcServerEntry server_entry;
418 SilcChannelEntry channel;
421 SilcIDPayload idp = NULL;
424 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
427 idp = silc_id_payload_parse_data(id_data, id_len);
431 name = silc_argument_get_arg_type(cmd->args, 3, &len);
432 info = silc_argument_get_arg_type(cmd->args, 4, &len);
434 id_type = silc_id_payload_get_type(idp);
438 client_id = silc_id_payload_get_id(idp);
442 SILC_LOG_DEBUG(("Received client information"));
444 client = silc_idlist_find_client_by_id(server->local_list,
445 client_id, FALSE, NULL);
447 client = silc_idlist_find_client_by_id(server->global_list, client_id,
452 /* If router did not find such Client ID in its lists then this must
453 be bogus client or some router in the net is buggy. */
454 if (server->server_type == SILC_ROUTER)
457 /* Take hostname out of nick string if it includes it. */
459 if (strchr(name, '@')) {
460 int len = strcspn(name, "@");
461 nick = silc_calloc(len + 1, sizeof(char));
462 memcpy(nick, name, len);
468 /* We don't have that client anywhere, add it. The client is added
469 to global list since server didn't have it in the lists so it must be
471 client = silc_idlist_add_client(server->global_list, nick,
472 info ? strdup(info) : NULL, NULL,
473 client_id, cmd->sock->user_data, NULL);
475 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
478 client->data.registered = TRUE;
480 /* We have the client already, update the data */
482 SILC_LOG_DEBUG(("Updating client data"));
484 /* Take hostname out of nick string if it includes it. */
486 if (strchr(name, '@')) {
487 int len = strcspn(name, "@");
488 nick = silc_calloc(len + 1, sizeof(char));
489 memcpy(nick, name, len);
495 if (name && client->nickname)
496 silc_free(client->nickname);
499 client->nickname = nick;
501 if (info && client->username) {
502 silc_free(client->username);
503 client->username = strdup(info);
506 /* Remove the old cache entry and create a new one */
508 silc_idcache_del_by_context(global ? server->global_list->clients :
509 server->local_list->clients, client);
510 silc_idcache_add(global ? server->global_list->clients :
511 server->local_list->clients, nick, client->id,
515 silc_free(client_id);
521 server_id = silc_id_payload_get_id(idp);
525 SILC_LOG_DEBUG(("Received server information"));
527 server_entry = silc_idlist_find_server_by_id(server->local_list,
528 server_id, FALSE, NULL);
530 server_entry = silc_idlist_find_server_by_id(server->global_list,
531 server_id, FALSE, NULL);
533 /* If router did not find such Server ID in its lists then this must
534 be bogus client or some router in the net is buggy. */
535 if (server->server_type == SILC_ROUTER)
538 /* We don't have that server anywhere, add it. */
539 server_entry = silc_idlist_add_server(server->global_list,
541 server_id, NULL, NULL);
543 silc_free(server_id);
546 server_entry->data.registered = TRUE;
550 silc_free(server_id);
553 case SILC_ID_CHANNEL:
554 channel_id = silc_id_payload_get_id(idp);
558 SILC_LOG_DEBUG(("Received channel information"));
560 channel = silc_idlist_find_channel_by_id(server->local_list,
563 channel = silc_idlist_find_channel_by_id(server->global_list, channel_id,
566 /* If router did not find such Server ID in its lists then this must
567 be bogus client or some router in the net is buggy. */
568 if (server->server_type == SILC_ROUTER)
571 /* We don't have that server anywhere, add it. */
572 channel = silc_idlist_add_channel(server->global_list, strdup(name),
573 SILC_CHANNEL_MODE_NONE, channel_id,
574 server->router->connection,
577 silc_free(channel_id);
583 silc_free(channel_id);
587 silc_id_payload_free(idp);
591 silc_id_payload_free(idp);
595 /* Received reply for forwarded IDENTIFY command. We have received the
596 requested identify information now and we will cache it. After this we
597 will call the pending command so that the requestee gets the information
600 SILC_SERVER_CMD_REPLY_FUNC(identify)
602 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
603 SilcCommandStatus status;
605 COMMAND_CHECK_STATUS_LIST;
607 if (!silc_server_command_reply_identify_save(cmd))
610 /* Pending callbacks are not executed if this was an list entry */
611 if (status != SILC_STATUS_OK &&
612 status != SILC_STATUS_LIST_END) {
613 silc_server_command_reply_free(cmd);
618 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
619 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_IDENTIFY);
620 silc_server_command_reply_free(cmd);
623 /* Received reply fro INFO command. Cache the server and its information */
625 SILC_SERVER_CMD_REPLY_FUNC(info)
627 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
628 SilcServer server = cmd->server;
629 SilcCommandStatus status;
630 SilcServerEntry entry;
631 SilcServerID *server_id;
633 unsigned char *tmp, *name;
635 COMMAND_CHECK_STATUS;
638 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
641 server_id = silc_id_payload_parse_id(tmp, tmp_len);
646 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
650 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
653 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
656 /* Add the server to global list */
657 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
658 entry = silc_idlist_add_server(server->global_list, name, 0,
659 server_id, NULL, NULL);
661 silc_free(server_id);
664 entry->data.registered = TRUE;
668 /* Get the info string */
669 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
673 entry->server_info = tmp ? strdup(tmp) : NULL;
676 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
677 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO);
678 silc_server_command_reply_free(cmd);
681 /* Received reply fro MOTD command. */
683 SILC_SERVER_CMD_REPLY_FUNC(motd)
685 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
686 SilcServer server = cmd->server;
687 SilcCommandStatus status;
688 SilcServerEntry entry = NULL;
689 SilcServerID *server_id;
693 COMMAND_CHECK_STATUS;
696 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
699 server_id = silc_id_payload_parse_id(tmp, tmp_len);
703 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
706 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
713 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
720 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
721 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_MOTD);
722 silc_server_command_reply_free(cmd);
728 /* Received reply for forwarded JOIN command. Router has created or joined
729 the client to the channel. We save some channel information locally
732 SILC_SERVER_CMD_REPLY_FUNC(join)
734 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
735 SilcServer server = cmd->server;
736 SilcIDCacheEntry cache = NULL;
737 SilcCommandStatus status;
739 SilcClientID *client_id = NULL;
740 SilcChannelEntry entry;
741 SilcHmac hmac = NULL;
742 uint32 id_len, len, list_count;
743 unsigned char *id_string;
744 char *channel_name, *tmp;
745 uint32 mode, created;
746 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
748 COMMAND_CHECK_STATUS;
750 /* Get channel name */
751 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
756 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
761 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
764 client_id = silc_id_payload_parse_id(tmp, len);
769 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
772 SILC_GET32_MSB(mode, tmp);
774 /* Get created boolean value */
775 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
778 SILC_GET32_MSB(created, tmp);
779 if (created != 0 && created != 1)
782 /* Get channel key */
783 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
785 keyp = silc_buffer_alloc(len);
786 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
787 silc_buffer_put(keyp, tmp, len);
790 id = silc_id_payload_parse_id(id_string, id_len);
795 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
797 if (!silc_hmac_alloc(tmp, NULL, &hmac))
801 /* Get the list count */
802 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
805 SILC_GET32_MSB(list_count, tmp);
807 /* Get Client ID list */
808 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
812 client_id_list = silc_buffer_alloc(len);
813 silc_buffer_pull_tail(client_id_list, len);
814 silc_buffer_put(client_id_list, tmp, len);
816 /* Get client mode list */
817 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
821 client_mode_list = silc_buffer_alloc(len);
822 silc_buffer_pull_tail(client_mode_list, len);
823 silc_buffer_put(client_mode_list, tmp, len);
825 /* See whether we already have the channel. */
826 entry = silc_idlist_find_channel_by_name(server->local_list,
827 channel_name, &cache);
829 /* Add new channel */
831 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
832 (created == 0 ? "existing" : "created"), channel_name,
833 silc_id_render(id, SILC_ID_CHANNEL)));
835 /* Add the channel to our local list. */
836 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
837 SILC_CHANNEL_MODE_NONE, id,
838 server->router, NULL, hmac);
844 /* The entry exists. */
846 silc_free(cache->id);
848 cache->id = entry->id;
850 /* Remove the founder auth data if the mode is not set but we have
852 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
853 silc_pkcs_public_key_free(entry->founder_key);
854 if (entry->founder_passwd) {
855 silc_free(entry->founder_passwd);
856 entry->founder_passwd = NULL;
861 if (entry->hmac_name && hmac) {
862 silc_free(entry->hmac_name);
863 entry->hmac_name = strdup(hmac->hmac->name);
866 /* Get the ban list */
867 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
870 silc_free(entry->ban_list);
871 entry->ban_list = silc_calloc(len, sizeof(*entry->ban_list));
872 memcpy(entry->ban_list, tmp, len);
875 /* Get the invite list */
876 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
878 if (entry->invite_list)
879 silc_free(entry->invite_list);
880 entry->invite_list = silc_calloc(len, sizeof(*entry->invite_list));
881 memcpy(entry->invite_list, tmp, len);
885 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
888 silc_free(entry->topic);
889 entry->topic = strdup(tmp);
892 /* If channel was not created we know there is global users on the
894 entry->global_users = (created == 0 ? TRUE : FALSE);
896 /* If channel was just created the mask must be zero */
897 if (!entry->global_users && mode) {
898 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
899 "new channel, forcing it to zero", cmd->sock->hostname));
903 /* Save channel mode */
906 /* Save channel key */
907 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
908 silc_server_save_channel_key(server, keyp, entry);
910 silc_buffer_free(keyp);
912 /* Save the users to the channel */
913 silc_server_save_users_on_channel(server, cmd->sock, entry,
914 client_id, client_id_list,
915 client_mode_list, list_count);
918 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
919 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_JOIN);
921 silc_free(client_id);
922 silc_server_command_reply_free(cmd);
925 silc_buffer_free(client_id_list);
926 if (client_mode_list)
927 silc_buffer_free(client_mode_list);
930 SILC_SERVER_CMD_REPLY_FUNC(users)
932 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
933 SilcServer server = cmd->server;
934 SilcCommandStatus status;
935 SilcChannelEntry channel;
936 SilcChannelID *channel_id = NULL;
937 SilcBuffer client_id_list;
938 SilcBuffer client_mode_list;
943 COMMAND_CHECK_STATUS;
946 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
949 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
953 /* Get channel entry */
954 channel = silc_idlist_find_channel_by_id(server->local_list,
957 channel = silc_idlist_find_channel_by_id(server->global_list,
962 if (server->server_type == SILC_ROUTER)
965 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
966 silc_server_send_command(server, server->router->connection,
967 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
968 1, 5, idp->data, idp->len);
969 silc_buffer_free(idp);
971 /* Register pending command callback. After we've received the channel
972 information we will reprocess this command reply by re-calling this
973 USERS command reply callback. */
974 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
976 NULL, silc_server_command_reply_users, cmd);
981 /* Get the list count */
982 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
985 SILC_GET32_MSB(list_count, tmp);
987 /* Get Client ID list */
988 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
992 client_id_list = silc_buffer_alloc(tmp_len);
993 silc_buffer_pull_tail(client_id_list, tmp_len);
994 silc_buffer_put(client_id_list, tmp, tmp_len);
996 /* Get client mode list */
997 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1001 client_mode_list = silc_buffer_alloc(tmp_len);
1002 silc_buffer_pull_tail(client_mode_list, tmp_len);
1003 silc_buffer_put(client_mode_list, tmp, tmp_len);
1005 /* Save the users to the channel */
1006 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1007 client_id_list, client_mode_list,
1010 silc_buffer_free(client_id_list);
1011 silc_buffer_free(client_mode_list);
1014 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1015 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
1016 silc_free(channel_id);
1017 silc_server_command_reply_free(cmd);
1020 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1022 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1023 SilcServer server = cmd->server;
1024 SilcCommandStatus status;
1025 SilcClientEntry client = NULL;
1026 SilcServerEntry server_entry = NULL;
1027 SilcClientID *client_id = NULL;
1028 SilcServerID *server_id = NULL;
1030 unsigned char *tmp, *pk;
1033 SilcIDPayload idp = NULL;
1035 SilcPublicKey public_key = NULL;
1037 COMMAND_CHECK_STATUS;
1039 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1042 idp = silc_id_payload_parse_data(tmp, len);
1046 /* Get the public key payload */
1047 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1051 /* Decode the public key */
1053 SILC_GET16_MSB(pk_len, tmp);
1054 SILC_GET16_MSB(type, tmp + 2);
1057 if (type != SILC_SKE_PK_TYPE_SILC)
1060 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1063 id_type = silc_id_payload_get_type(idp);
1064 if (id_type == SILC_ID_CLIENT) {
1065 client_id = silc_id_payload_get_id(idp);
1067 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1070 client = silc_idlist_find_client_by_id(server->global_list,
1071 client_id, TRUE, NULL);
1076 client->data.public_key = public_key;
1077 } else if (id_type == SILC_ID_SERVER) {
1078 server_id = silc_id_payload_get_id(idp);
1080 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1082 if (!server_entry) {
1083 server_entry = silc_idlist_find_server_by_id(server->global_list,
1084 server_id, TRUE, NULL);
1089 server_entry->data.public_key = public_key;
1095 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1096 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
1098 silc_id_payload_free(idp);
1099 silc_free(client_id);
1100 silc_free(server_id);
1102 silc_pkcs_public_key_free(public_key);
1103 silc_server_command_reply_free(cmd);