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->data, buffer->len);
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 unsigned char *fingerprint;
138 SilcClientID *client_id;
139 SilcClientEntry client;
142 uint32 mode = 0, len, id_len, flen;
144 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
145 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
146 username = silc_argument_get_arg_type(cmd->args, 4, &len);
147 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
148 if (!id_data || !nickname || !username || !realname) {
149 SILC_LOG_ERROR(("Incomplete WHOIS info: %s %s %s",
150 nickname ? nickname : "",
151 username ? username : "",
152 realname ? realname : ""));
156 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
158 SILC_GET32_MSB(mode, tmp);
160 client_id = silc_id_payload_parse_id(id_data, id_len);
164 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
166 /* Check if we have this client cached already. */
168 client = silc_idlist_find_client_by_id(server->local_list, client_id,
171 client = silc_idlist_find_client_by_id(server->global_list, client_id,
177 /* If router did not find such Client ID in its lists then this must
178 be bogus client or some router in the net is buggy. */
179 if (server->server_type != SILC_SERVER)
182 /* Take hostname out of nick string if it includes it. */
183 silc_parse_userfqdn(nickname, &nick, &servername);
185 /* We don't have that client anywhere, add it. The client is added
186 to global list since server didn't have it in the lists so it must be
188 client = silc_idlist_add_client(server->global_list, nick,
190 strdup(realname), client_id,
191 cmd->sock->user_data, NULL);
193 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
197 client->data.status |=
198 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
199 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
201 client->servername = servername;
203 /* We have the client already, update the data */
205 SILC_LOG_DEBUG(("Updating client data"));
207 /* Take hostname out of nick string if it includes it. */
208 silc_parse_userfqdn(nickname, &nick, &servername);
210 /* Remove the old cache entry */
211 silc_idcache_del_by_context(global ? server->global_list->clients :
212 server->local_list->clients, client);
214 silc_free(client->nickname);
215 silc_free(client->username);
216 silc_free(client->userinfo);
217 silc_free(client->servername);
219 client->nickname = nick;
220 client->username = strdup(username);
221 client->userinfo = strdup(realname);
222 client->servername = servername;
224 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
225 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
227 /* Create new cache entry */
228 silc_idcache_add(global ? server->global_list->clients :
229 server->local_list->clients, nick, client->id,
231 silc_free(client_id);
234 if (fingerprint && flen == sizeof(client->data.fingerprint))
235 memcpy(client->data.fingerprint, fingerprint, flen);
240 /* Reiceved reply for WHOIS command. We sent the whois request to our
241 primary router, if we are normal server, and thus has now received reply
242 to the command. We will figure out what client originally sent us the
243 command and will send the reply to it. If we are router we will figure
244 out who server sent us the command and send reply to that one. */
246 SILC_SERVER_CMD_REPLY_FUNC(whois)
248 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
249 SilcCommandStatus status;
251 COMMAND_CHECK_STATUS_LIST;
253 if (!silc_server_command_reply_whois_save(cmd))
256 /* Pending callbacks are not executed if this was an list entry */
257 if (status != SILC_STATUS_OK &&
258 status != SILC_STATUS_LIST_END) {
259 silc_server_command_reply_free(cmd);
264 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
265 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS);
266 silc_server_command_reply_free(cmd);
269 /* Caches the received WHOWAS information for a short period of time. */
272 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
274 SilcServer server = cmd->server;
276 unsigned char *id_data;
277 char *nickname, *username, *realname, *servername = NULL;
278 SilcClientID *client_id;
279 SilcClientEntry client;
280 SilcIDCacheEntry cache = NULL;
284 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
285 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
286 username = silc_argument_get_arg_type(cmd->args, 4, &len);
287 if (!id_data || !nickname || !username)
290 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
292 client_id = silc_id_payload_parse_id(id_data, id_len);
296 /* Check if we have this client cached already. */
298 client = silc_idlist_find_client_by_id(server->local_list, client_id,
301 client = silc_idlist_find_client_by_id(server->global_list,
302 client_id, FALSE, &cache);
307 /* If router did not find such Client ID in its lists then this must
308 be bogus client or some router in the net is buggy. */
309 if (server->server_type != SILC_SERVER)
312 /* Take hostname out of nick string if it includes it. */
313 silc_parse_userfqdn(nickname, &nick, &servername);
315 /* We don't have that client anywhere, add it. The client is added
316 to global list since server didn't have it in the lists so it must be
318 client = silc_idlist_add_client(server->global_list, nick,
319 strdup(username), strdup(realname),
320 silc_id_dup(client_id, SILC_ID_CLIENT),
321 cmd->sock->user_data, NULL);
323 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
327 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
328 client = silc_idlist_find_client_by_id(server->global_list,
329 client_id, TRUE, &cache);
330 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
331 client->servername = servername;
333 /* We have the client already, update the data */
335 /* Take hostname out of nick string if it includes it. */
336 silc_parse_userfqdn(nickname, &nick, &servername);
338 silc_free(client->nickname);
339 silc_free(client->username);
341 client->nickname = nick;
342 client->username = strdup(username);
343 client->servername = servername;
345 /* Remove the old cache entry and create a new one */
346 silc_idcache_del_by_context(global ? server->global_list->clients :
347 server->local_list->clients, client);
348 silc_idcache_add(global ? server->global_list->clients :
349 server->local_list->clients, nick, client->id,
353 silc_free(client_id);
358 /* Received reply for WHOWAS command. Cache the client information only for
359 a short period of time. */
361 SILC_SERVER_CMD_REPLY_FUNC(whowas)
363 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
364 SilcCommandStatus status;
366 COMMAND_CHECK_STATUS_LIST;
368 if (!silc_server_command_reply_whowas_save(cmd))
371 /* Pending callbacks are not executed if this was an list entry */
372 if (status != SILC_STATUS_OK &&
373 status != SILC_STATUS_LIST_END) {
374 silc_server_command_reply_free(cmd);
379 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
380 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOWAS);
381 silc_server_command_reply_free(cmd);
384 /* Caches the received IDENTIFY information. */
387 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
389 SilcServer server = cmd->server;
391 unsigned char *id_data;
393 SilcClientID *client_id = NULL;
394 SilcServerID *server_id = NULL;
395 SilcChannelID *channel_id = NULL;
396 SilcClientEntry client;
397 SilcServerEntry server_entry;
398 SilcChannelEntry channel;
401 SilcIDPayload idp = NULL;
404 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
407 idp = silc_id_payload_parse(id_data, id_len);
411 name = silc_argument_get_arg_type(cmd->args, 3, &len);
412 info = silc_argument_get_arg_type(cmd->args, 4, &len);
414 id_type = silc_id_payload_get_type(idp);
418 client_id = silc_id_payload_get_id(idp);
422 SILC_LOG_DEBUG(("Received client information"));
424 client = silc_idlist_find_client_by_id(server->local_list,
425 client_id, FALSE, NULL);
427 client = silc_idlist_find_client_by_id(server->global_list, client_id,
432 /* If router did not find such Client ID in its lists then this must
433 be bogus client or some router in the net is buggy. */
434 if (server->server_type != SILC_SERVER)
439 silc_parse_userfqdn(name, &nick, NULL);
441 /* We don't have that client anywhere, add it. The client is added
442 to global list since server didn't have it in the lists so it must be
444 client = silc_idlist_add_client(server->global_list, nick,
445 info ? strdup(info) : NULL, NULL,
446 client_id, cmd->sock->user_data, NULL);
448 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
451 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
452 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
453 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
455 /* We have the client already, update the data */
457 SILC_LOG_DEBUG(("Updating client data"));
461 silc_parse_userfqdn(name, &nick, NULL);
463 /* Remove the old cache entry */
464 silc_idcache_del_by_context(global ? server->global_list->clients :
465 server->local_list->clients, client);
467 silc_free(client->nickname);
468 client->nickname = nick;
472 silc_free(client->username);
473 client->username = strdup(info);
476 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
477 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
480 /* Add new cache entry */
481 silc_idcache_add(global ? server->global_list->clients :
482 server->local_list->clients, nick, client->id,
486 silc_free(client_id);
492 server_id = silc_id_payload_get_id(idp);
496 SILC_LOG_DEBUG(("Received server information"));
498 server_entry = silc_idlist_find_server_by_id(server->local_list,
499 server_id, FALSE, NULL);
501 server_entry = silc_idlist_find_server_by_id(server->global_list,
502 server_id, FALSE, NULL);
504 /* If router did not find such Server ID in its lists then this must
505 be bogus server or some router in the net is buggy. */
506 if (server->server_type != SILC_SERVER)
509 /* We don't have that server anywhere, add it. */
510 server_entry = silc_idlist_add_server(server->global_list,
512 server_id, NULL, NULL);
514 silc_free(server_id);
517 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
518 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
519 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
523 silc_free(server_id);
526 case SILC_ID_CHANNEL:
527 channel_id = silc_id_payload_get_id(idp);
531 SILC_LOG_DEBUG(("Received channel information"));
534 channel = silc_idlist_find_channel_by_name(server->local_list,
537 channel = silc_idlist_find_channel_by_name(server->global_list,
540 channel = silc_idlist_find_channel_by_id(server->local_list,
543 channel = silc_idlist_find_channel_by_id(server->global_list,
547 /* If router did not find such Channel ID in its lists then this must
548 be bogus channel or some router in the net is buggy. */
549 if (server->server_type != SILC_SERVER)
552 /* We don't have that server anywhere, add it. */
553 channel = silc_idlist_add_channel(server->global_list, strdup(name),
554 SILC_CHANNEL_MODE_NONE, channel_id,
558 silc_free(channel_id);
564 silc_free(channel_id);
568 silc_id_payload_free(idp);
572 silc_id_payload_free(idp);
576 /* Received reply for forwarded IDENTIFY command. We have received the
577 requested identify information now and we will cache it. After this we
578 will call the pending command so that the requestee gets the information
581 SILC_SERVER_CMD_REPLY_FUNC(identify)
583 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
584 SilcCommandStatus status;
586 COMMAND_CHECK_STATUS_LIST;
588 if (!silc_server_command_reply_identify_save(cmd))
591 /* Pending callbacks are not executed if this was an list entry */
592 if (status != SILC_STATUS_OK &&
593 status != SILC_STATUS_LIST_END) {
594 silc_server_command_reply_free(cmd);
599 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
600 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_IDENTIFY);
601 silc_server_command_reply_free(cmd);
604 /* Received reply fro INFO command. Cache the server and its information */
606 SILC_SERVER_CMD_REPLY_FUNC(info)
608 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
609 SilcServer server = cmd->server;
610 SilcCommandStatus status;
611 SilcServerEntry entry;
612 SilcServerID *server_id;
614 unsigned char *tmp, *name;
616 COMMAND_CHECK_STATUS;
619 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
622 server_id = silc_id_payload_parse_id(tmp, tmp_len);
627 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
631 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
634 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
637 /* Add the server to global list */
638 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
639 entry = silc_idlist_add_server(server->global_list, name, 0,
640 server_id, NULL, NULL);
642 silc_free(server_id);
645 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
649 /* Get the info string */
650 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
654 entry->server_info = tmp ? strdup(tmp) : NULL;
657 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
658 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO);
659 silc_server_command_reply_free(cmd);
662 /* Received reply fro MOTD command. */
664 SILC_SERVER_CMD_REPLY_FUNC(motd)
666 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
667 SilcServer server = cmd->server;
668 SilcCommandStatus status;
669 SilcServerEntry entry = NULL;
670 SilcServerID *server_id;
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);
684 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
687 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
694 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
701 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
702 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_MOTD);
703 silc_server_command_reply_free(cmd);
709 /* Received reply for forwarded JOIN command. Router has created or joined
710 the client to the channel. We save some channel information locally
713 SILC_SERVER_CMD_REPLY_FUNC(join)
715 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
716 SilcServer server = cmd->server;
717 SilcIDCacheEntry cache = NULL;
718 SilcCommandStatus status;
720 SilcClientID *client_id = NULL;
721 SilcChannelEntry entry;
722 SilcHmac hmac = NULL;
723 uint32 id_len, len, list_count;
724 unsigned char *id_string;
725 char *channel_name, *tmp;
726 uint32 mode, created;
727 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
729 COMMAND_CHECK_STATUS;
731 /* Get channel name */
732 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
737 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
742 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
745 client_id = silc_id_payload_parse_id(tmp, len);
750 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
753 SILC_GET32_MSB(mode, tmp);
755 /* Get created boolean value */
756 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
759 SILC_GET32_MSB(created, tmp);
760 if (created != 0 && created != 1)
763 /* Get channel key */
764 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
766 keyp = silc_buffer_alloc(len);
767 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
768 silc_buffer_put(keyp, tmp, len);
771 id = silc_id_payload_parse_id(id_string, id_len);
776 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
778 if (!silc_hmac_alloc(tmp, NULL, &hmac))
782 /* Get the list count */
783 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
786 SILC_GET32_MSB(list_count, tmp);
788 /* Get Client ID list */
789 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
793 client_id_list = silc_buffer_alloc(len);
794 silc_buffer_pull_tail(client_id_list, len);
795 silc_buffer_put(client_id_list, tmp, len);
797 /* Get client mode list */
798 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
802 client_mode_list = silc_buffer_alloc(len);
803 silc_buffer_pull_tail(client_mode_list, len);
804 silc_buffer_put(client_mode_list, tmp, len);
806 /* See whether we already have the channel. */
807 entry = silc_idlist_find_channel_by_name(server->local_list,
808 channel_name, &cache);
810 /* Add new channel */
812 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
813 (created == 0 ? "existing" : "created"), channel_name,
814 silc_id_render(id, SILC_ID_CHANNEL)));
816 /* If the channel is found from global list we must move it to the
818 entry = silc_idlist_find_channel_by_name(server->global_list,
819 channel_name, &cache);
821 silc_idlist_del_channel(server->global_list, entry);
823 /* Add the channel to our local list. */
824 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
825 SILC_CHANNEL_MODE_NONE, id,
826 server->router, NULL, hmac);
831 server->stat.my_channels++;
833 /* The entry exists. */
834 silc_free(cache->id);
836 cache->id = entry->id;
837 entry->disabled = FALSE;
839 /* Remove the founder auth data if the mode is not set but we have
841 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
842 silc_pkcs_public_key_free(entry->founder_key);
843 if (entry->founder_passwd) {
844 silc_free(entry->founder_passwd);
845 entry->founder_passwd = NULL;
850 if (entry->hmac_name && hmac) {
851 silc_free(entry->hmac_name);
852 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
855 /* Get the ban list */
856 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
859 silc_free(entry->ban_list);
860 entry->ban_list = silc_calloc(len, sizeof(*entry->ban_list));
861 memcpy(entry->ban_list, tmp, len);
864 /* Get the invite list */
865 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
867 if (entry->invite_list)
868 silc_free(entry->invite_list);
869 entry->invite_list = silc_calloc(len, sizeof(*entry->invite_list));
870 memcpy(entry->invite_list, tmp, len);
874 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
877 silc_free(entry->topic);
878 entry->topic = strdup(tmp);
881 /* If channel was not created we know there is global users on the
883 entry->global_users = (created == 0 ? TRUE : FALSE);
885 /* If channel was just created the mask must be zero */
886 if (!entry->global_users && mode) {
887 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
888 "new channel, forcing it to zero", cmd->sock->hostname));
892 /* Save channel mode */
895 /* Save channel key */
896 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
897 silc_server_save_channel_key(server, keyp, entry);
899 silc_buffer_free(keyp);
901 /* Save the users to the channel */
902 silc_server_save_users_on_channel(server, cmd->sock, entry,
903 client_id, client_id_list,
904 client_mode_list, list_count);
907 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
908 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_JOIN);
909 silc_free(client_id);
910 silc_server_command_reply_free(cmd);
913 silc_buffer_free(client_id_list);
914 if (client_mode_list)
915 silc_buffer_free(client_mode_list);
918 SILC_SERVER_CMD_REPLY_FUNC(users)
920 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
921 SilcServer server = cmd->server;
922 SilcCommandStatus status;
923 SilcChannelEntry channel;
924 SilcChannelID *channel_id = NULL;
925 SilcBuffer client_id_list;
926 SilcBuffer client_mode_list;
931 COMMAND_CHECK_STATUS;
934 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
937 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
941 /* Get channel entry */
942 channel = silc_idlist_find_channel_by_id(server->local_list,
945 channel = silc_idlist_find_channel_by_id(server->global_list,
950 if (server->server_type != SILC_SERVER)
953 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
954 silc_server_send_command(server, server->router->connection,
955 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
956 1, 5, idp->data, idp->len);
957 silc_buffer_free(idp);
959 /* Register pending command callback. After we've received the channel
960 information we will reprocess this command reply by re-calling this
961 USERS command reply callback. */
962 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
964 NULL, silc_server_command_reply_users, cmd);
969 /* Get the list count */
970 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
973 SILC_GET32_MSB(list_count, tmp);
975 /* Get Client ID list */
976 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
980 client_id_list = silc_buffer_alloc(tmp_len);
981 silc_buffer_pull_tail(client_id_list, tmp_len);
982 silc_buffer_put(client_id_list, tmp, tmp_len);
984 /* Get client mode list */
985 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
989 client_mode_list = silc_buffer_alloc(tmp_len);
990 silc_buffer_pull_tail(client_mode_list, tmp_len);
991 silc_buffer_put(client_mode_list, tmp, tmp_len);
993 /* Save the users to the channel */
994 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
995 client_id_list, client_mode_list,
998 silc_buffer_free(client_id_list);
999 silc_buffer_free(client_mode_list);
1002 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1003 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
1004 silc_free(channel_id);
1005 silc_server_command_reply_free(cmd);
1008 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1010 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1011 SilcServer server = cmd->server;
1012 SilcCommandStatus status;
1013 SilcClientEntry client = NULL;
1014 SilcServerEntry server_entry = NULL;
1015 SilcClientID *client_id = NULL;
1016 SilcServerID *server_id = NULL;
1018 unsigned char *tmp, *pk;
1021 SilcIDPayload idp = NULL;
1023 SilcPublicKey public_key = NULL;
1025 COMMAND_CHECK_STATUS;
1027 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1030 idp = silc_id_payload_parse(tmp, len);
1034 /* Get the public key payload */
1035 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1039 /* Decode the public key */
1041 SILC_GET16_MSB(pk_len, tmp);
1042 SILC_GET16_MSB(type, tmp + 2);
1045 if (type != SILC_SKE_PK_TYPE_SILC)
1048 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1051 id_type = silc_id_payload_get_type(idp);
1052 if (id_type == SILC_ID_CLIENT) {
1053 client_id = silc_id_payload_get_id(idp);
1055 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1058 client = silc_idlist_find_client_by_id(server->global_list,
1059 client_id, TRUE, NULL);
1064 client->data.public_key = public_key;
1065 } else if (id_type == SILC_ID_SERVER) {
1066 server_id = silc_id_payload_get_id(idp);
1068 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1070 if (!server_entry) {
1071 server_entry = silc_idlist_find_server_by_id(server->global_list,
1072 server_id, TRUE, NULL);
1077 server_entry->data.public_key = public_key;
1083 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1084 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_GETKEY);
1086 silc_id_payload_free(idp);
1087 silc_free(client_id);
1088 silc_free(server_id);
1090 silc_pkcs_public_key_free(public_key);
1091 silc_server_command_reply_free(cmd);
1094 SILC_SERVER_CMD_REPLY_FUNC(list)
1096 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1097 SilcServer server = cmd->server;
1098 SilcCommandStatus status;
1099 SilcChannelID *channel_id = NULL;
1100 SilcChannelEntry channel;
1102 unsigned char *tmp, *name, *topic;
1103 uint32 usercount = 0;
1105 COMMAND_CHECK_STATUS_LIST;
1107 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1108 channel_id = silc_id_payload_parse_id(tmp, len);
1112 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1113 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1114 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1116 SILC_GET32_MSB(usercount, tmp);
1118 /* Add the channel entry if we do not have it already */
1119 channel = silc_idlist_find_channel_by_name(server->local_list,
1122 channel = silc_idlist_find_channel_by_name(server->global_list,
1125 /* If router did not find such Channel ID in its lists then this must
1126 be bogus channel or some router in the net is buggy. */
1127 if (server->server_type != SILC_SERVER)
1130 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1131 SILC_CHANNEL_MODE_NONE, channel_id,
1132 server->router, NULL, NULL);
1139 silc_free(channel->topic);
1140 channel->topic = strdup(topic);
1143 /* Pending callbacks are not executed if this was an list entry */
1144 if (status != SILC_STATUS_OK &&
1145 status != SILC_STATUS_LIST_END) {
1146 silc_server_command_reply_free(cmd);
1151 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1152 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_LIST);
1153 silc_free(channel_id);
1154 silc_server_command_reply_free(cmd);