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 SilcUInt32 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, NULL);
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, NULL);
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_server_remove_from_channels(server, NULL, client, TRUE,
290 silc_idlist_del_client(server->global_list, client);
292 silc_free(client_id);
297 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
298 silc_server_command_reply_free(cmd);
301 /* Caches the received WHOWAS information for a short period of time. */
304 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
306 SilcServer server = cmd->server;
307 SilcUInt32 len, id_len;
308 unsigned char *id_data;
309 char *nickname, *username, *realname, *servername = NULL;
310 SilcClientID *client_id;
311 SilcClientEntry client;
312 SilcIDCacheEntry cache = NULL;
316 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
317 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
318 username = silc_argument_get_arg_type(cmd->args, 4, &len);
319 if (!id_data || !nickname || !username)
322 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
324 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
328 /* Check if we have this client cached already. */
330 client = silc_idlist_find_client_by_id(server->local_list, client_id,
333 client = silc_idlist_find_client_by_id(server->global_list,
334 client_id, FALSE, &cache);
339 /* If router did not find such Client ID in its lists then this must
340 be bogus client or some router in the net is buggy. */
341 if (server->server_type != SILC_SERVER)
344 /* Take hostname out of nick string if it includes it. */
345 silc_parse_userfqdn(nickname, &nick, &servername);
347 /* We don't have that client anywhere, add it. The client is added
348 to global list since server didn't have it in the lists so it must be
350 client = silc_idlist_add_client(server->global_list, nick,
351 strdup(username), strdup(realname),
352 silc_id_dup(client_id, SILC_ID_CLIENT),
353 cmd->sock->user_data, NULL,
354 SILC_ID_CACHE_EXPIRE_DEF);
356 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
360 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
361 client->servername = servername;
363 /* We have the client already, update the data */
365 /* Take hostname out of nick string if it includes it. */
366 silc_parse_userfqdn(nickname, &nick, &servername);
368 silc_free(client->nickname);
369 silc_free(client->username);
371 client->nickname = nick;
372 client->username = strdup(username);
373 client->servername = servername;
375 /* Remove the old cache entry and create a new one */
376 silc_idcache_del_by_context(global ? server->global_list->clients :
377 server->local_list->clients, client);
378 silc_idcache_add(global ? server->global_list->clients :
379 server->local_list->clients, nick, client->id,
383 silc_free(client_id);
388 /* Received reply for WHOWAS command. Cache the client information only for
389 a short period of time. */
391 SILC_SERVER_CMD_REPLY_FUNC(whowas)
393 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
394 SilcCommandStatus status;
396 COMMAND_CHECK_STATUS_LIST;
398 if (!silc_server_command_reply_whowas_save(cmd))
401 /* Pending callbacks are not executed if this was an list entry */
402 if (status != SILC_STATUS_OK &&
403 status != SILC_STATUS_LIST_END) {
404 silc_server_command_reply_free(cmd);
409 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
410 silc_server_command_reply_free(cmd);
413 /* Caches the received IDENTIFY information. */
416 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
418 SilcServer server = cmd->server;
419 SilcUInt32 len, id_len;
420 unsigned char *id_data;
422 SilcClientID *client_id = NULL;
423 SilcServerID *server_id = NULL;
424 SilcChannelID *channel_id = NULL;
425 SilcClientEntry client;
426 SilcServerEntry server_entry;
427 SilcChannelEntry channel;
430 SilcIDPayload idp = NULL;
434 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
437 idp = silc_id_payload_parse(id_data, id_len);
441 name = silc_argument_get_arg_type(cmd->args, 3, &len);
442 info = silc_argument_get_arg_type(cmd->args, 4, &len);
444 id_type = silc_id_payload_get_type(idp);
448 client_id = silc_id_payload_get_id(idp);
452 SILC_LOG_DEBUG(("Received client information"));
454 client = silc_idlist_find_client_by_id(server->local_list,
455 client_id, FALSE, NULL);
457 client = silc_idlist_find_client_by_id(server->global_list, client_id,
462 /* If router did not find such Client ID in its lists then this must
463 be bogus client or some router in the net is buggy. */
464 if (server->server_type != SILC_SERVER)
469 silc_parse_userfqdn(name, &nick, NULL);
471 /* We don't have that client anywhere, add it. The client is added
472 to global list since server didn't have it in the lists so it must be
474 client = silc_idlist_add_client(server->global_list, nick,
475 info ? strdup(info) : NULL, NULL,
476 client_id, cmd->sock->user_data, NULL,
479 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
482 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
483 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
484 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
486 /* We have the client already, update the data */
488 SILC_LOG_DEBUG(("Updating client data"));
492 silc_parse_userfqdn(name, &nick, NULL);
494 /* Remove the old cache entry */
495 silc_idcache_del_by_context(global ? server->global_list->clients :
496 server->local_list->clients, client);
498 silc_free(client->nickname);
499 client->nickname = nick;
503 silc_free(client->username);
504 client->username = strdup(info);
507 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
508 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
511 /* If client is global and is not on any channel then add that we'll
512 expire the entry after a while. */
513 if (global && !silc_hash_table_count(client->channels) &&
514 server->server_type == SILC_SERVER)
515 expire = time(NULL) + 300;
517 /* Add new cache entry */
518 silc_idcache_add(global ? server->global_list->clients :
519 server->local_list->clients, nick, client->id,
520 client, expire, NULL);
523 silc_free(client_id);
532 server_id = silc_id_payload_get_id(idp);
536 SILC_LOG_DEBUG(("Received server information"));
538 server_entry = silc_idlist_find_server_by_id(server->local_list,
539 server_id, FALSE, NULL);
541 server_entry = silc_idlist_find_server_by_id(server->global_list,
542 server_id, FALSE, NULL);
544 /* If router did not find such Server ID in its lists then this must
545 be bogus server or some router in the net is buggy. */
546 if (server->server_type != SILC_SERVER)
549 /* We don't have that server anywhere, add it. */
550 server_entry = silc_idlist_add_server(server->global_list,
552 server_id, NULL, NULL);
554 silc_free(server_id);
557 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
558 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
559 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
563 silc_free(server_id);
566 case SILC_ID_CHANNEL:
570 channel_id = silc_id_payload_get_id(idp);
574 SILC_LOG_DEBUG(("Received channel information"));
576 channel = silc_idlist_find_channel_by_name(server->local_list,
579 channel = silc_idlist_find_channel_by_name(server->global_list,
582 /* If router did not find such Channel ID in its lists then this must
583 be bogus channel or some router in the net is buggy. */
584 if (server->server_type != SILC_SERVER)
587 /* We don't have that server anywhere, add it. */
588 channel = silc_idlist_add_channel(server->global_list, strdup(name),
589 SILC_CHANNEL_MODE_NONE, channel_id,
590 server->router, NULL, NULL, 0);
592 silc_free(channel_id);
598 silc_free(channel_id);
602 silc_id_payload_free(idp);
606 silc_id_payload_free(idp);
610 /* Received reply for forwarded IDENTIFY command. We have received the
611 requested identify information now and we will cache it. After this we
612 will call the pending command so that the requestee gets the information
615 SILC_SERVER_CMD_REPLY_FUNC(identify)
617 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
618 SilcServer server = cmd->server;
619 SilcCommandStatus status;
621 COMMAND_CHECK_STATUS_LIST;
623 if (!silc_server_command_reply_identify_save(cmd))
626 /* Pending callbacks are not executed if this was an list entry */
627 if (status != SILC_STATUS_OK &&
628 status != SILC_STATUS_LIST_END) {
629 silc_server_command_reply_free(cmd);
634 /* If we received notify for invalid ID we'll remove the ID if we
636 if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
637 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
638 SilcClientEntry client;
640 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
642 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
644 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
645 "the entry from cache"));
646 client = silc_idlist_find_client_by_id(server->global_list,
647 client_id, FALSE, NULL);
649 silc_server_remove_from_channels(server, NULL, client, TRUE,
651 silc_idlist_del_client(server->global_list, client);
653 silc_free(client_id);
658 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
659 silc_server_command_reply_free(cmd);
662 /* Received reply fro INFO command. Cache the server and its information */
664 SILC_SERVER_CMD_REPLY_FUNC(info)
666 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
667 SilcServer server = cmd->server;
668 SilcCommandStatus status;
669 SilcServerEntry entry;
670 SilcServerID *server_id;
672 unsigned char *tmp, *name;
674 COMMAND_CHECK_STATUS;
677 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
680 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
685 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
689 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
692 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
695 /* Add the server to global list */
696 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
697 entry = silc_idlist_add_server(server->global_list, name, 0,
698 server_id, NULL, NULL);
700 silc_free(server_id);
703 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
707 /* Get the info string */
708 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
712 entry->server_info = tmp ? strdup(tmp) : NULL;
715 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
716 silc_server_command_reply_free(cmd);
719 /* Received reply fro MOTD command. */
721 SILC_SERVER_CMD_REPLY_FUNC(motd)
723 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
724 SilcServer server = cmd->server;
725 SilcCommandStatus status;
726 SilcServerEntry entry = NULL;
727 SilcServerID *server_id;
731 COMMAND_CHECK_STATUS;
734 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
737 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
741 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
744 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
751 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
758 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
759 silc_server_command_reply_free(cmd);
765 /* Received reply for forwarded JOIN command. Router has created or joined
766 the client to the channel. We save some channel information locally
769 SILC_SERVER_CMD_REPLY_FUNC(join)
771 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
772 SilcServer server = cmd->server;
773 SilcIDCacheEntry cache = NULL;
774 SilcCommandStatus status;
776 SilcClientID *client_id = NULL;
777 SilcChannelEntry entry;
778 SilcHmac hmac = NULL;
779 SilcUInt32 id_len, len, list_count;
780 unsigned char *id_string;
781 char *channel_name, *tmp;
782 SilcUInt32 mode, created;
783 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
785 COMMAND_CHECK_STATUS;
787 /* Get channel name */
788 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
793 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
798 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
801 client_id = silc_id_payload_parse_id(tmp, len, NULL);
806 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
809 SILC_GET32_MSB(mode, tmp);
811 /* Get created boolean value */
812 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
815 SILC_GET32_MSB(created, tmp);
816 if (created != 0 && created != 1)
819 /* Get channel key */
820 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
822 keyp = silc_buffer_alloc(len);
823 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
824 silc_buffer_put(keyp, tmp, len);
827 /* Parse the Channel ID */
828 id = silc_id_payload_parse_id(id_string, id_len, NULL);
833 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
835 if (!silc_hmac_alloc(tmp, NULL, &hmac))
839 /* Get the list count */
840 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
843 SILC_GET32_MSB(list_count, tmp);
845 /* Get Client ID list */
846 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
850 client_id_list = silc_buffer_alloc(len);
851 silc_buffer_pull_tail(client_id_list, len);
852 silc_buffer_put(client_id_list, tmp, len);
854 /* Get client mode list */
855 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
859 client_mode_list = silc_buffer_alloc(len);
860 silc_buffer_pull_tail(client_mode_list, len);
861 silc_buffer_put(client_mode_list, tmp, len);
863 /* See whether we already have the channel. */
864 entry = silc_idlist_find_channel_by_name(server->local_list,
865 channel_name, &cache);
867 /* Add new channel */
869 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
870 (created == 0 ? "existing" : "created"), channel_name,
871 silc_id_render(id, SILC_ID_CHANNEL)));
873 /* If the channel is found from global list we must move it to the
875 entry = silc_idlist_find_channel_by_name(server->global_list,
876 channel_name, &cache);
879 silc_schedule_task_del_by_context(server->schedule, entry->rekey);
880 SILC_LOG_ERROR(("global_list->channels: entry->rekey != NULL, inform Pekka now!!!"));
882 silc_idlist_del_channel(server->global_list, entry);
885 /* Add the channel to our local list. */
886 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
887 SILC_CHANNEL_MODE_NONE, id,
888 server->router, NULL, hmac, 0);
893 server->stat.my_channels++;
895 /* The entry exists. */
897 /* If ID has changed, then update it to the cache too. */
898 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
899 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
901 entry->disabled = FALSE;
903 /* Remove the founder auth data if the mode is not set but we have
905 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
906 silc_pkcs_public_key_free(entry->founder_key);
907 silc_free(entry->founder_passwd);
908 entry->founder_passwd = NULL;
912 if (entry->hmac_name && hmac) {
913 silc_free(entry->hmac_name);
914 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
917 /* Get the ban list */
918 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
920 silc_free(entry->ban_list);
921 entry->ban_list = silc_memdup(tmp, len);
924 /* Get the invite list */
925 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
927 silc_free(entry->invite_list);
928 entry->invite_list = silc_memdup(tmp, len);
932 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
934 silc_free(entry->topic);
935 entry->topic = strdup(tmp);
938 /* If channel was not created we know there is global users on the
940 entry->global_users = (created == 0 ? TRUE : FALSE);
942 /* If channel was just created the mask must be zero */
943 if (!entry->global_users && mode) {
944 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
945 "new channel, forcing it to zero", cmd->sock->hostname));
949 /* Save channel mode */
952 /* Save channel key */
954 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
955 silc_server_save_channel_key(server, keyp, entry);
956 silc_buffer_free(keyp);
959 /* Save the users to the channel */
960 silc_server_save_users_on_channel(server, cmd->sock, entry,
961 client_id, client_id_list,
962 client_mode_list, list_count);
965 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
966 silc_free(client_id);
967 silc_server_command_reply_free(cmd);
970 silc_buffer_free(client_id_list);
971 if (client_mode_list)
972 silc_buffer_free(client_mode_list);
975 SILC_SERVER_CMD_REPLY_FUNC(users)
977 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
978 SilcServer server = cmd->server;
979 SilcCommandStatus status;
980 SilcChannelEntry channel;
981 SilcChannelID *channel_id = NULL;
982 SilcBuffer client_id_list;
983 SilcBuffer client_mode_list;
986 SilcUInt32 list_count;
988 COMMAND_CHECK_STATUS;
991 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
994 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
998 /* Get channel entry */
999 channel = silc_idlist_find_channel_by_id(server->local_list,
1002 channel = silc_idlist_find_channel_by_id(server->global_list,
1007 if (server->server_type != SILC_SERVER)
1010 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1011 silc_server_send_command(server, server->router->connection,
1012 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1013 1, 5, idp->data, idp->len);
1014 silc_buffer_free(idp);
1016 /* Register pending command callback. After we've received the channel
1017 information we will reprocess this command reply by re-calling this
1018 USERS command reply callback. */
1019 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1021 silc_server_command_reply_users, cmd);
1026 /* Get the list count */
1027 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1030 SILC_GET32_MSB(list_count, tmp);
1032 /* Get Client ID list */
1033 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1037 client_id_list = silc_buffer_alloc(tmp_len);
1038 silc_buffer_pull_tail(client_id_list, tmp_len);
1039 silc_buffer_put(client_id_list, tmp, tmp_len);
1041 /* Get client mode list */
1042 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1046 client_mode_list = silc_buffer_alloc(tmp_len);
1047 silc_buffer_pull_tail(client_mode_list, tmp_len);
1048 silc_buffer_put(client_mode_list, tmp, tmp_len);
1050 /* Save the users to the channel */
1051 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1052 client_id_list, client_mode_list,
1055 silc_buffer_free(client_id_list);
1056 silc_buffer_free(client_mode_list);
1059 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1060 silc_free(channel_id);
1061 silc_server_command_reply_free(cmd);
1064 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1066 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1067 SilcServer server = cmd->server;
1068 SilcCommandStatus status;
1069 SilcClientEntry client = NULL;
1070 SilcServerEntry server_entry = NULL;
1071 SilcClientID *client_id = NULL;
1072 SilcServerID *server_id = NULL;
1074 unsigned char *tmp, *pk;
1077 SilcIDPayload idp = NULL;
1079 SilcPublicKey public_key = NULL;
1081 COMMAND_CHECK_STATUS;
1083 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1086 idp = silc_id_payload_parse(tmp, len);
1090 /* Get the public key payload */
1091 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1095 /* Decode the public key */
1097 SILC_GET16_MSB(pk_len, tmp);
1098 SILC_GET16_MSB(type, tmp + 2);
1101 if (type != SILC_SKE_PK_TYPE_SILC)
1104 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1107 id_type = silc_id_payload_get_type(idp);
1108 if (id_type == SILC_ID_CLIENT) {
1109 client_id = silc_id_payload_get_id(idp);
1111 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1114 client = silc_idlist_find_client_by_id(server->global_list,
1115 client_id, TRUE, NULL);
1120 client->data.public_key = public_key;
1121 } else if (id_type == SILC_ID_SERVER) {
1122 server_id = silc_id_payload_get_id(idp);
1124 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1126 if (!server_entry) {
1127 server_entry = silc_idlist_find_server_by_id(server->global_list,
1128 server_id, TRUE, NULL);
1133 server_entry->data.public_key = public_key;
1139 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1141 silc_id_payload_free(idp);
1142 silc_free(client_id);
1143 silc_free(server_id);
1145 silc_pkcs_public_key_free(public_key);
1146 silc_server_command_reply_free(cmd);
1149 SILC_SERVER_CMD_REPLY_FUNC(list)
1151 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1152 SilcServer server = cmd->server;
1153 SilcCommandStatus status;
1154 SilcChannelID *channel_id = NULL;
1155 SilcChannelEntry channel;
1156 SilcIDCacheEntry cache;
1158 unsigned char *tmp, *name, *topic;
1159 SilcUInt32 usercount = 0;
1160 bool global_list = FALSE;
1162 COMMAND_CHECK_STATUS_LIST;
1164 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1165 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1169 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1170 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1171 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1173 SILC_GET32_MSB(usercount, tmp);
1175 /* Add the channel entry if we do not have it already */
1176 channel = silc_idlist_find_channel_by_name(server->local_list,
1179 channel = silc_idlist_find_channel_by_name(server->global_list,
1184 /* If router did not find such channel in its lists then this must
1185 be bogus channel or some router in the net is buggy. */
1186 if (server->server_type != SILC_SERVER)
1189 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1190 SILC_CHANNEL_MODE_NONE, channel_id,
1191 server->router, NULL, NULL,
1197 /* Found, update expiry */
1198 if (global_list && server->server_type == SILC_SERVER)
1199 cache->expire = time(NULL) + 60;
1202 channel->user_count = usercount;
1205 silc_free(channel->topic);
1206 channel->topic = strdup(topic);
1209 /* Pending callbacks are not executed if this was an list entry */
1210 if (status != SILC_STATUS_OK &&
1211 status != SILC_STATUS_LIST_END) {
1212 silc_server_command_reply_free(cmd);
1216 /* Now purge all old entries from the global list, otherwise we'll might
1217 have non-existent entries for long periods of time in the cache. */
1218 silc_idcache_purge(server->global_list->channels);
1221 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1222 silc_free(channel_id);
1223 silc_server_command_reply_free(cmd);