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;
145 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
146 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
147 username = silc_argument_get_arg_type(cmd->args, 4, &len);
148 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
149 if (!id_data || !nickname || !username || !realname) {
150 SILC_LOG_ERROR(("Incomplete WHOIS info: %s %s %s",
151 nickname ? nickname : "",
152 username ? username : "",
153 realname ? realname : ""));
157 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
159 SILC_GET32_MSB(mode, tmp);
161 client_id = silc_id_payload_parse_id(id_data, id_len);
165 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
167 /* Check if we have this client cached already. */
169 client = silc_idlist_find_client_by_id(server->local_list, client_id,
172 client = silc_idlist_find_client_by_id(server->global_list, client_id,
178 /* If router did not find such Client ID in its lists then this must
179 be bogus client or some router in the net is buggy. */
180 if (server->server_type != SILC_SERVER)
183 /* Take hostname out of nick string if it includes it. */
184 silc_parse_userfqdn(nickname, &nick, &servername);
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,
195 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
199 client->data.status |=
200 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
201 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
203 client->servername = servername;
205 /* We have the client already, update the data */
207 SILC_LOG_DEBUG(("Updating client data"));
209 /* Take hostname out of nick string if it includes it. */
210 silc_parse_userfqdn(nickname, &nick, &servername);
212 /* Remove the old cache entry */
213 silc_idcache_del_by_context(global ? server->global_list->clients :
214 server->local_list->clients, client);
216 silc_free(client->nickname);
217 silc_free(client->username);
218 silc_free(client->userinfo);
219 silc_free(client->servername);
221 client->nickname = nick;
222 client->username = strdup(username);
223 client->userinfo = strdup(realname);
224 client->servername = servername;
226 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
227 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
229 /* If client is global and is not on any channel then add that we'll
230 expire the entry after a while. */
231 if (global && !silc_hash_table_count(client->channels) &&
232 server->server_type == SILC_SERVER)
233 expire = time(NULL) + 300;
235 /* Create new cache entry */
236 silc_idcache_add(global ? server->global_list->clients :
237 server->local_list->clients, nick, client->id,
238 client, expire, NULL);
239 silc_free(client_id);
242 if (fingerprint && flen == sizeof(client->data.fingerprint))
243 memcpy(client->data.fingerprint, fingerprint, flen);
248 /* Reiceved reply for WHOIS command. We sent the whois request to our
249 primary router, if we are normal server, and thus has now received reply
250 to the command. We will figure out what client originally sent us the
251 command and will send the reply to it. If we are router we will figure
252 out who server sent us the command and send reply to that one. */
254 SILC_SERVER_CMD_REPLY_FUNC(whois)
256 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
257 SilcServer server = cmd->server;
258 SilcCommandStatus status;
260 COMMAND_CHECK_STATUS_LIST;
262 if (!silc_server_command_reply_whois_save(cmd))
265 /* Pending callbacks are not executed if this was an list entry */
266 if (status != SILC_STATUS_OK &&
267 status != SILC_STATUS_LIST_END) {
268 silc_server_command_reply_free(cmd);
273 /* If we received notify for invalid ID we'll remove the ID if we
275 if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
276 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
277 SilcClientEntry client;
279 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
281 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
283 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
284 "the entry from cache"));
285 client = silc_idlist_find_client_by_id(server->global_list,
286 client_id, FALSE, NULL);
288 silc_idlist_del_client(server->global_list, client);
289 silc_free(client_id);
294 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
295 silc_server_command_reply_free(cmd);
298 /* Caches the received WHOWAS information for a short period of time. */
301 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
303 SilcServer server = cmd->server;
305 unsigned char *id_data;
306 char *nickname, *username, *realname, *servername = NULL;
307 SilcClientID *client_id;
308 SilcClientEntry client;
309 SilcIDCacheEntry cache = NULL;
313 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
314 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
315 username = silc_argument_get_arg_type(cmd->args, 4, &len);
316 if (!id_data || !nickname || !username)
319 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
321 client_id = silc_id_payload_parse_id(id_data, id_len);
325 /* Check if we have this client cached already. */
327 client = silc_idlist_find_client_by_id(server->local_list, client_id,
330 client = silc_idlist_find_client_by_id(server->global_list,
331 client_id, FALSE, &cache);
336 /* If router did not find such Client ID in its lists then this must
337 be bogus client or some router in the net is buggy. */
338 if (server->server_type != SILC_SERVER)
341 /* Take hostname out of nick string if it includes it. */
342 silc_parse_userfqdn(nickname, &nick, &servername);
344 /* We don't have that client anywhere, add it. The client is added
345 to global list since server didn't have it in the lists so it must be
347 client = silc_idlist_add_client(server->global_list, nick,
348 strdup(username), strdup(realname),
349 silc_id_dup(client_id, SILC_ID_CLIENT),
350 cmd->sock->user_data, NULL,
351 SILC_ID_CACHE_EXPIRE_DEF);
353 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
357 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
358 client->servername = servername;
360 /* We have the client already, update the data */
362 /* Take hostname out of nick string if it includes it. */
363 silc_parse_userfqdn(nickname, &nick, &servername);
365 silc_free(client->nickname);
366 silc_free(client->username);
368 client->nickname = nick;
369 client->username = strdup(username);
370 client->servername = servername;
372 /* Remove the old cache entry and create a new one */
373 silc_idcache_del_by_context(global ? server->global_list->clients :
374 server->local_list->clients, client);
375 silc_idcache_add(global ? server->global_list->clients :
376 server->local_list->clients, nick, client->id,
380 silc_free(client_id);
385 /* Received reply for WHOWAS command. Cache the client information only for
386 a short period of time. */
388 SILC_SERVER_CMD_REPLY_FUNC(whowas)
390 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
391 SilcCommandStatus status;
393 COMMAND_CHECK_STATUS_LIST;
395 if (!silc_server_command_reply_whowas_save(cmd))
398 /* Pending callbacks are not executed if this was an list entry */
399 if (status != SILC_STATUS_OK &&
400 status != SILC_STATUS_LIST_END) {
401 silc_server_command_reply_free(cmd);
406 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
407 silc_server_command_reply_free(cmd);
410 /* Caches the received IDENTIFY information. */
413 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
415 SilcServer server = cmd->server;
417 unsigned char *id_data;
419 SilcClientID *client_id = NULL;
420 SilcServerID *server_id = NULL;
421 SilcChannelID *channel_id = NULL;
422 SilcClientEntry client;
423 SilcServerEntry server_entry;
424 SilcChannelEntry channel;
427 SilcIDPayload idp = NULL;
431 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
434 idp = silc_id_payload_parse(id_data, id_len);
438 name = silc_argument_get_arg_type(cmd->args, 3, &len);
439 info = silc_argument_get_arg_type(cmd->args, 4, &len);
441 id_type = silc_id_payload_get_type(idp);
445 client_id = silc_id_payload_get_id(idp);
449 SILC_LOG_DEBUG(("Received client information"));
451 client = silc_idlist_find_client_by_id(server->local_list,
452 client_id, FALSE, NULL);
454 client = silc_idlist_find_client_by_id(server->global_list, client_id,
459 /* If router did not find such Client ID in its lists then this must
460 be bogus client or some router in the net is buggy. */
461 if (server->server_type != SILC_SERVER)
466 silc_parse_userfqdn(name, &nick, NULL);
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,
476 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
479 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
480 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
481 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
483 /* We have the client already, update the data */
485 SILC_LOG_DEBUG(("Updating client data"));
489 silc_parse_userfqdn(name, &nick, NULL);
491 /* Remove the old cache entry */
492 silc_idcache_del_by_context(global ? server->global_list->clients :
493 server->local_list->clients, client);
495 silc_free(client->nickname);
496 client->nickname = nick;
500 silc_free(client->username);
501 client->username = strdup(info);
504 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
505 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
508 /* If client is global and is not on any channel then add that we'll
509 expire the entry after a while. */
510 if (global && !silc_hash_table_count(client->channels) &&
511 server->server_type == SILC_SERVER)
512 expire = time(NULL) + 300;
514 /* Add new cache entry */
515 silc_idcache_add(global ? server->global_list->clients :
516 server->local_list->clients, nick, client->id,
517 client, expire, NULL);
520 silc_free(client_id);
529 server_id = silc_id_payload_get_id(idp);
533 SILC_LOG_DEBUG(("Received server information"));
535 server_entry = silc_idlist_find_server_by_id(server->local_list,
536 server_id, FALSE, NULL);
538 server_entry = silc_idlist_find_server_by_id(server->global_list,
539 server_id, FALSE, NULL);
541 /* If router did not find such Server ID in its lists then this must
542 be bogus server or some router in the net is buggy. */
543 if (server->server_type != SILC_SERVER)
546 /* We don't have that server anywhere, add it. */
547 server_entry = silc_idlist_add_server(server->global_list,
549 server_id, NULL, NULL);
551 silc_free(server_id);
554 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
555 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
556 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
560 silc_free(server_id);
563 case SILC_ID_CHANNEL:
567 channel_id = silc_id_payload_get_id(idp);
571 SILC_LOG_DEBUG(("Received channel information"));
573 channel = silc_idlist_find_channel_by_name(server->local_list,
576 channel = silc_idlist_find_channel_by_name(server->global_list,
579 /* If router did not find such Channel ID in its lists then this must
580 be bogus channel or some router in the net is buggy. */
581 if (server->server_type != SILC_SERVER)
584 /* We don't have that server anywhere, add it. */
585 channel = silc_idlist_add_channel(server->global_list, strdup(name),
586 SILC_CHANNEL_MODE_NONE, channel_id,
587 server->router, NULL, NULL, 0);
589 silc_free(channel_id);
595 silc_free(channel_id);
599 silc_id_payload_free(idp);
603 silc_id_payload_free(idp);
607 /* Received reply for forwarded IDENTIFY command. We have received the
608 requested identify information now and we will cache it. After this we
609 will call the pending command so that the requestee gets the information
612 SILC_SERVER_CMD_REPLY_FUNC(identify)
614 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
615 SilcServer server = cmd->server;
616 SilcCommandStatus status;
618 COMMAND_CHECK_STATUS_LIST;
620 if (!silc_server_command_reply_identify_save(cmd))
623 /* Pending callbacks are not executed if this was an list entry */
624 if (status != SILC_STATUS_OK &&
625 status != SILC_STATUS_LIST_END) {
626 silc_server_command_reply_free(cmd);
631 /* If we received notify for invalid ID we'll remove the ID if we
633 if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
634 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
635 SilcClientEntry client;
637 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
639 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
641 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
642 "the entry from cache"));
643 client = silc_idlist_find_client_by_id(server->global_list,
644 client_id, FALSE, NULL);
646 silc_idlist_del_client(server->global_list, client);
647 silc_free(client_id);
652 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
653 silc_server_command_reply_free(cmd);
656 /* Received reply fro INFO command. Cache the server and its information */
658 SILC_SERVER_CMD_REPLY_FUNC(info)
660 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
661 SilcServer server = cmd->server;
662 SilcCommandStatus status;
663 SilcServerEntry entry;
664 SilcServerID *server_id;
666 unsigned char *tmp, *name;
668 COMMAND_CHECK_STATUS;
671 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
674 server_id = silc_id_payload_parse_id(tmp, tmp_len);
679 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
683 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
686 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
689 /* Add the server to global list */
690 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
691 entry = silc_idlist_add_server(server->global_list, name, 0,
692 server_id, NULL, NULL);
694 silc_free(server_id);
697 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
701 /* Get the info string */
702 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
706 entry->server_info = tmp ? strdup(tmp) : NULL;
709 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
710 silc_server_command_reply_free(cmd);
713 /* Received reply fro MOTD command. */
715 SILC_SERVER_CMD_REPLY_FUNC(motd)
717 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
718 SilcServer server = cmd->server;
719 SilcCommandStatus status;
720 SilcServerEntry entry = NULL;
721 SilcServerID *server_id;
725 COMMAND_CHECK_STATUS;
728 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
731 server_id = silc_id_payload_parse_id(tmp, tmp_len);
735 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
738 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
745 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
752 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
753 silc_server_command_reply_free(cmd);
759 /* Received reply for forwarded JOIN command. Router has created or joined
760 the client to the channel. We save some channel information locally
763 SILC_SERVER_CMD_REPLY_FUNC(join)
765 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
766 SilcServer server = cmd->server;
767 SilcIDCacheEntry cache = NULL;
768 SilcCommandStatus status;
770 SilcClientID *client_id = NULL;
771 SilcChannelEntry entry;
772 SilcHmac hmac = NULL;
773 uint32 id_len, len, list_count;
774 unsigned char *id_string;
775 char *channel_name, *tmp;
776 uint32 mode, created;
777 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
779 COMMAND_CHECK_STATUS;
781 /* Get channel name */
782 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
787 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
792 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
795 client_id = silc_id_payload_parse_id(tmp, len);
800 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
803 SILC_GET32_MSB(mode, tmp);
805 /* Get created boolean value */
806 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
809 SILC_GET32_MSB(created, tmp);
810 if (created != 0 && created != 1)
813 /* Get channel key */
814 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
816 keyp = silc_buffer_alloc(len);
817 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
818 silc_buffer_put(keyp, tmp, len);
821 id = silc_id_payload_parse_id(id_string, id_len);
826 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
828 if (!silc_hmac_alloc(tmp, NULL, &hmac))
832 /* Get the list count */
833 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
836 SILC_GET32_MSB(list_count, tmp);
838 /* Get Client ID list */
839 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
843 client_id_list = silc_buffer_alloc(len);
844 silc_buffer_pull_tail(client_id_list, len);
845 silc_buffer_put(client_id_list, tmp, len);
847 /* Get client mode list */
848 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
852 client_mode_list = silc_buffer_alloc(len);
853 silc_buffer_pull_tail(client_mode_list, len);
854 silc_buffer_put(client_mode_list, tmp, len);
856 /* See whether we already have the channel. */
857 entry = silc_idlist_find_channel_by_name(server->local_list,
858 channel_name, &cache);
860 /* Add new channel */
862 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
863 (created == 0 ? "existing" : "created"), channel_name,
864 silc_id_render(id, SILC_ID_CHANNEL)));
866 /* If the channel is found from global list we must move it to the
868 entry = silc_idlist_find_channel_by_name(server->global_list,
869 channel_name, &cache);
871 silc_idlist_del_channel(server->global_list, entry);
873 /* Add the channel to our local list. */
874 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
875 SILC_CHANNEL_MODE_NONE, id,
876 server->router, NULL, hmac, 0);
881 server->stat.my_channels++;
883 /* The entry exists. */
884 silc_free(cache->id);
886 cache->id = entry->id;
887 entry->disabled = FALSE;
889 /* Remove the founder auth data if the mode is not set but we have
891 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
892 silc_pkcs_public_key_free(entry->founder_key);
893 if (entry->founder_passwd) {
894 silc_free(entry->founder_passwd);
895 entry->founder_passwd = NULL;
900 if (entry->hmac_name && hmac) {
901 silc_free(entry->hmac_name);
902 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
905 /* Get the ban list */
906 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
909 silc_free(entry->ban_list);
910 entry->ban_list = silc_calloc(len, sizeof(*entry->ban_list));
911 memcpy(entry->ban_list, tmp, len);
914 /* Get the invite list */
915 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
917 if (entry->invite_list)
918 silc_free(entry->invite_list);
919 entry->invite_list = silc_calloc(len, sizeof(*entry->invite_list));
920 memcpy(entry->invite_list, tmp, len);
924 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
927 silc_free(entry->topic);
928 entry->topic = strdup(tmp);
931 /* If channel was not created we know there is global users on the
933 entry->global_users = (created == 0 ? TRUE : FALSE);
935 /* If channel was just created the mask must be zero */
936 if (!entry->global_users && mode) {
937 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
938 "new channel, forcing it to zero", cmd->sock->hostname));
942 /* Save channel mode */
945 /* Save channel key */
946 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
947 silc_server_save_channel_key(server, keyp, entry);
949 silc_buffer_free(keyp);
951 /* Save the users to the channel */
952 silc_server_save_users_on_channel(server, cmd->sock, entry,
953 client_id, client_id_list,
954 client_mode_list, list_count);
957 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
958 silc_free(client_id);
959 silc_server_command_reply_free(cmd);
962 silc_buffer_free(client_id_list);
963 if (client_mode_list)
964 silc_buffer_free(client_mode_list);
967 SILC_SERVER_CMD_REPLY_FUNC(users)
969 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
970 SilcServer server = cmd->server;
971 SilcCommandStatus status;
972 SilcChannelEntry channel;
973 SilcChannelID *channel_id = NULL;
974 SilcBuffer client_id_list;
975 SilcBuffer client_mode_list;
980 COMMAND_CHECK_STATUS;
983 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
986 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
990 /* Get channel entry */
991 channel = silc_idlist_find_channel_by_id(server->local_list,
994 channel = silc_idlist_find_channel_by_id(server->global_list,
999 if (server->server_type != SILC_SERVER)
1002 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1003 silc_server_send_command(server, server->router->connection,
1004 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1005 1, 5, idp->data, idp->len);
1006 silc_buffer_free(idp);
1008 /* Register pending command callback. After we've received the channel
1009 information we will reprocess this command reply by re-calling this
1010 USERS command reply callback. */
1011 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1013 silc_server_command_reply_users, cmd);
1018 /* Get the list count */
1019 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1022 SILC_GET32_MSB(list_count, tmp);
1024 /* Get Client ID list */
1025 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1029 client_id_list = silc_buffer_alloc(tmp_len);
1030 silc_buffer_pull_tail(client_id_list, tmp_len);
1031 silc_buffer_put(client_id_list, tmp, tmp_len);
1033 /* Get client mode list */
1034 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1038 client_mode_list = silc_buffer_alloc(tmp_len);
1039 silc_buffer_pull_tail(client_mode_list, tmp_len);
1040 silc_buffer_put(client_mode_list, tmp, tmp_len);
1042 /* Save the users to the channel */
1043 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1044 client_id_list, client_mode_list,
1047 silc_buffer_free(client_id_list);
1048 silc_buffer_free(client_mode_list);
1051 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1052 silc_free(channel_id);
1053 silc_server_command_reply_free(cmd);
1056 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1058 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1059 SilcServer server = cmd->server;
1060 SilcCommandStatus status;
1061 SilcClientEntry client = NULL;
1062 SilcServerEntry server_entry = NULL;
1063 SilcClientID *client_id = NULL;
1064 SilcServerID *server_id = NULL;
1066 unsigned char *tmp, *pk;
1069 SilcIDPayload idp = NULL;
1071 SilcPublicKey public_key = NULL;
1073 COMMAND_CHECK_STATUS;
1075 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1078 idp = silc_id_payload_parse(tmp, len);
1082 /* Get the public key payload */
1083 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1087 /* Decode the public key */
1089 SILC_GET16_MSB(pk_len, tmp);
1090 SILC_GET16_MSB(type, tmp + 2);
1093 if (type != SILC_SKE_PK_TYPE_SILC)
1096 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1099 id_type = silc_id_payload_get_type(idp);
1100 if (id_type == SILC_ID_CLIENT) {
1101 client_id = silc_id_payload_get_id(idp);
1103 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1106 client = silc_idlist_find_client_by_id(server->global_list,
1107 client_id, TRUE, NULL);
1112 client->data.public_key = public_key;
1113 } else if (id_type == SILC_ID_SERVER) {
1114 server_id = silc_id_payload_get_id(idp);
1116 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1118 if (!server_entry) {
1119 server_entry = silc_idlist_find_server_by_id(server->global_list,
1120 server_id, TRUE, NULL);
1125 server_entry->data.public_key = public_key;
1131 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1133 silc_id_payload_free(idp);
1134 silc_free(client_id);
1135 silc_free(server_id);
1137 silc_pkcs_public_key_free(public_key);
1138 silc_server_command_reply_free(cmd);
1141 SILC_SERVER_CMD_REPLY_FUNC(list)
1143 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1144 SilcServer server = cmd->server;
1145 SilcCommandStatus status;
1146 SilcChannelID *channel_id = NULL;
1147 SilcChannelEntry channel;
1148 SilcIDCacheEntry cache;
1150 unsigned char *tmp, *name, *topic;
1151 uint32 usercount = 0;
1152 bool global_list = FALSE;
1154 COMMAND_CHECK_STATUS_LIST;
1156 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1157 channel_id = silc_id_payload_parse_id(tmp, len);
1161 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1162 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1163 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1165 SILC_GET32_MSB(usercount, tmp);
1167 /* Add the channel entry if we do not have it already */
1168 channel = silc_idlist_find_channel_by_name(server->local_list,
1171 channel = silc_idlist_find_channel_by_name(server->global_list,
1176 /* If router did not find such channel in its lists then this must
1177 be bogus channel or some router in the net is buggy. */
1178 if (server->server_type != SILC_SERVER)
1181 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1182 SILC_CHANNEL_MODE_NONE, channel_id,
1183 server->router, NULL, NULL,
1189 /* Found, update expiry */
1190 if (global_list && server->server_type == SILC_SERVER)
1191 cache->expire = time(NULL) + 60;
1195 silc_free(channel->topic);
1196 channel->topic = strdup(topic);
1199 /* Pending callbacks are not executed if this was an list entry */
1200 if (status != SILC_STATUS_OK &&
1201 status != SILC_STATUS_LIST_END) {
1202 silc_server_command_reply_free(cmd);
1206 /* Now purge all old entries from the global list, otherwise we'll might
1207 have non-existent entries for long periods of time in the cache. */
1208 silc_idcache_purge(server->global_list->channels);
1211 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1212 silc_free(channel_id);
1213 silc_server_command_reply_free(cmd);