5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 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 macros must have
27 out: and err: goto labels. */
29 #define COMMAND_CHECK_STATUS \
31 SILC_LOG_DEBUG(("Start")); \
32 if (!silc_command_get_status(cmd->payload, &status, &error)) { \
33 if (SILC_STATUS_IS_ERROR(status)) \
35 if (status == SILC_STATUS_LIST_END) \
41 /* Server command reply list. Not all commands have reply function as
42 they are never sent by server. More maybe added later if need appears. */
43 SilcServerCommandReply silc_command_reply_list[] =
45 SILC_SERVER_CMD_REPLY(whois, WHOIS),
46 SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
47 SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
48 SILC_SERVER_CMD_REPLY(info, INFO),
49 SILC_SERVER_CMD_REPLY(motd, MOTD),
50 SILC_SERVER_CMD_REPLY(join, JOIN),
51 SILC_SERVER_CMD_REPLY(stats, STATS),
52 SILC_SERVER_CMD_REPLY(users, USERS),
53 SILC_SERVER_CMD_REPLY(getkey, GETKEY),
54 SILC_SERVER_CMD_REPLY(list, LIST),
59 /* Process received command reply. */
61 void silc_server_command_reply_process(SilcServer server,
62 SilcSocketConnection sock,
65 SilcServerCommandReply *cmd;
66 SilcServerCommandReplyContext ctx;
67 SilcCommandPayload payload;
70 SILC_LOG_DEBUG(("Start"));
72 /* Get command reply payload from packet */
73 payload = silc_command_payload_parse(buffer->data, buffer->len);
75 /* Silently ignore bad reply packet */
76 SILC_LOG_DEBUG(("Bad command reply packet"));
80 /* Allocate command reply context. This must be free'd by the
81 command reply routine receiving it. */
82 ctx = silc_calloc(1, sizeof(*ctx));
84 ctx->sock = silc_socket_dup(sock);
85 ctx->payload = payload;
86 ctx->args = silc_command_get_args(ctx->payload);
87 ctx->ident = silc_command_get_ident(ctx->payload);
89 /* Check for pending commands and mark to be exeucted */
91 silc_server_command_pending_check(server, silc_command_get(ctx->payload),
92 ctx->ident, &ctx->callbacks_count);
94 /* Execute command reply */
95 command = silc_command_get(ctx->payload);
96 for (cmd = silc_command_reply_list; cmd->cb; cmd++)
97 if (cmd->cmd == command)
100 if (cmd == NULL || !cmd->cb) {
101 silc_server_command_reply_free(ctx);
108 /* Free command reply context and its internals. */
110 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
113 silc_command_payload_free(cmd->payload);
115 silc_socket_free(cmd->sock); /* Decrease the reference counter */
116 silc_free(cmd->callbacks);
122 silc_server_command_process_error(SilcServerCommandReplyContext cmd,
125 SilcServer server = cmd->server;
127 /* If we received notify for invalid ID we'll remove the ID if we
129 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
130 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
131 SilcClientEntry client;
133 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
135 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
137 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
138 "the entry from cache"));
139 client = silc_idlist_find_client_by_id(server->global_list,
140 client_id, FALSE, NULL);
142 silc_server_remove_from_channels(server, NULL, client, TRUE,
144 silc_idlist_del_data(client);
145 silc_idlist_del_client(server->global_list, client);
147 silc_free(client_id);
153 /* Caches the received WHOIS information. */
156 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
158 SilcServer server = cmd->server;
159 unsigned char *tmp, *id_data, *umodes;
160 char *nickname, *username, *realname, *servername = NULL;
161 unsigned char *fingerprint;
162 SilcClientID *client_id;
163 SilcClientEntry client;
164 SilcIDCacheEntry cache = NULL;
167 SilcUInt32 mode = 0, len, len2, id_len, flen;
169 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
170 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
171 username = silc_argument_get_arg_type(cmd->args, 4, &len);
172 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
173 if (!id_data || !nickname || !username || !realname)
176 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
178 SILC_GET32_MSB(mode, tmp);
180 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
184 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
186 /* Check if we have this client cached already. */
188 client = silc_idlist_find_client_by_id(server->local_list, client_id,
191 client = silc_idlist_find_client_by_id(server->global_list, client_id,
197 /* If router did not find such Client ID in its lists then this must
198 be bogus client or some router in the net is buggy. */
199 if (server->server_type != SILC_SERVER)
202 /* Take hostname out of nick string if it includes it. */
203 silc_parse_userfqdn(nickname, &nick, &servername);
205 /* We don't have that client anywhere, add it. The client is added
206 to global list since server didn't have it in the lists so it must be
208 client = silc_idlist_add_client(server->global_list, nick,
210 strdup(realname), client_id,
211 cmd->sock->user_data, NULL, 0);
213 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
217 client->data.status |=
218 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
219 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
221 client->servername = servername;
223 /* We have the client already, update the data */
225 SILC_LOG_DEBUG(("Updating client data"));
227 /* Take hostname out of nick string if it includes it. */
228 silc_parse_userfqdn(nickname, &nick, &servername);
230 /* Remove the old cache entry */
231 silc_idcache_del_by_context(global ? server->global_list->clients :
232 server->local_list->clients, client);
234 silc_free(client->nickname);
235 silc_free(client->username);
236 silc_free(client->userinfo);
237 silc_free(client->servername);
239 client->nickname = nick;
240 client->username = strdup(username);
241 client->userinfo = strdup(realname);
242 client->servername = servername;
244 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
245 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
247 /* Create new cache entry */
248 silc_idcache_add(global ? server->global_list->clients :
249 server->local_list->clients, nick, client->id,
251 silc_free(client_id);
254 /* Save channel list if it was sent to us */
255 if (server->server_type == SILC_SERVER) {
256 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
257 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
259 SilcBufferStruct channels_buf, umodes_buf;
260 silc_buffer_set(&channels_buf, tmp, len);
261 silc_buffer_set(&umodes_buf, umodes, len2);
262 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
265 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
268 /* If client is global and is not on any channel then add that we'll
269 expire the entry after a while. */
271 silc_idlist_find_client_by_id(server->global_list, client->id,
273 if (!silc_hash_table_count(client->channels))
274 cache->expire = time(NULL) + 300;
280 if (fingerprint && flen == sizeof(client->data.fingerprint))
281 memcpy(client->data.fingerprint, fingerprint, flen);
283 /* Take Requested Attributes if set. */
284 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
286 silc_free(client->attrs);
287 client->attrs = silc_memdup(tmp, len);
293 /* Handle requested attributes reply in WHOIS from client */
296 silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd)
300 SilcClientEntry client = cmd->sock->user_data;
302 /* Take Requested Attributes if set. */
303 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
305 silc_free(client->attrs);
306 client->attrs = silc_memdup(tmp, len);
312 /* Reiceved reply for WHOIS command. We sent the whois request to our
313 primary router, if we are normal server, and thus has now received reply
314 to the command. We will figure out what client originally sent us the
315 command and will send the reply to it. If we are router we will figure
316 out who server sent us the command and send reply to that one. */
318 SILC_SERVER_CMD_REPLY_FUNC(whois)
320 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
321 SilcStatus status, error;
323 COMMAND_CHECK_STATUS;
325 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) {
326 if (!silc_server_command_reply_whois_save(cmd))
329 if (!silc_server_command_reply_whois_save_client(cmd))
333 /* Pending callbacks are not executed if this was an list entry */
334 if (status != SILC_STATUS_OK &&
335 status != SILC_STATUS_LIST_END) {
336 silc_server_command_reply_free(cmd);
341 silc_server_command_process_error(cmd, error);
342 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
343 silc_server_command_reply_free(cmd);
347 silc_server_command_process_error(cmd, error);
348 silc_server_command_reply_free(cmd);
351 /* Caches the received WHOWAS information for a short period of time. */
354 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
356 SilcServer server = cmd->server;
357 SilcUInt32 len, id_len;
358 unsigned char *id_data;
359 char *nickname, *username, *realname, *servername = NULL;
360 SilcClientID *client_id;
361 SilcClientEntry client;
362 SilcIDCacheEntry cache = NULL;
366 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
367 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
368 username = silc_argument_get_arg_type(cmd->args, 4, &len);
369 if (!id_data || !nickname || !username)
372 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
374 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
378 /* Check if we have this client cached already. */
380 client = silc_idlist_find_client_by_id(server->local_list, client_id,
383 client = silc_idlist_find_client_by_id(server->global_list,
384 client_id, FALSE, &cache);
389 /* If router did not find such Client ID in its lists then this must
390 be bogus client or some router in the net is buggy. */
391 if (server->server_type != SILC_SERVER)
394 /* Take hostname out of nick string if it includes it. */
395 silc_parse_userfqdn(nickname, &nick, &servername);
397 /* We don't have that client anywhere, add it. The client is added
398 to global list since server didn't have it in the lists so it must be
400 client = silc_idlist_add_client(server->global_list, nick,
401 strdup(username), strdup(realname),
402 silc_id_dup(client_id, SILC_ID_CLIENT),
403 cmd->sock->user_data, NULL,
404 SILC_ID_CACHE_EXPIRE_DEF);
406 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
410 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
411 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
412 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
413 client->servername = servername;
415 /* We have the client already, update the data */
417 /* Take hostname out of nick string if it includes it. */
418 silc_parse_userfqdn(nickname, &nick, &servername);
420 silc_free(client->nickname);
421 silc_free(client->username);
422 silc_free(client->servername);
424 client->nickname = nick;
425 client->username = strdup(username);
426 client->servername = servername;
427 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
428 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
430 /* Remove the old cache entry and create a new one */
431 silc_idcache_del_by_context(global ? server->global_list->clients :
432 server->local_list->clients, client);
433 silc_idcache_add(global ? server->global_list->clients :
434 server->local_list->clients, nick, client->id,
438 /* If client is global and is not on any channel then add that we'll
439 expire the entry after a while. */
441 silc_idlist_find_client_by_id(server->global_list, client->id,
443 if (!silc_hash_table_count(client->channels))
444 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
449 silc_free(client_id);
454 /* Received reply for WHOWAS command. Cache the client information only for
455 a short period of time. */
457 SILC_SERVER_CMD_REPLY_FUNC(whowas)
459 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
460 SilcStatus status, error;
462 COMMAND_CHECK_STATUS;
464 if (!silc_server_command_reply_whowas_save(cmd))
467 /* Pending callbacks are not executed if this was an list entry */
468 if (status != SILC_STATUS_OK &&
469 status != SILC_STATUS_LIST_END) {
470 silc_server_command_reply_free(cmd);
475 silc_server_command_process_error(cmd, error);
476 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
477 silc_server_command_reply_free(cmd);
481 silc_server_command_process_error(cmd, error);
482 silc_server_command_reply_free(cmd);
485 /* Caches the received IDENTIFY information. */
488 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
490 SilcServer server = cmd->server;
491 SilcUInt32 len, id_len;
492 unsigned char *id_data;
494 SilcClientID *client_id = NULL;
495 SilcServerID *server_id = NULL;
496 SilcChannelID *channel_id = NULL;
497 SilcClientEntry client;
498 SilcServerEntry server_entry;
499 SilcChannelEntry channel;
502 SilcIDPayload idp = NULL;
506 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
509 idp = silc_id_payload_parse(id_data, id_len);
513 name = silc_argument_get_arg_type(cmd->args, 3, &len);
514 info = silc_argument_get_arg_type(cmd->args, 4, &len);
516 id_type = silc_id_payload_get_type(idp);
520 client_id = silc_id_payload_get_id(idp);
524 SILC_LOG_DEBUG(("Received client information"));
526 client = silc_idlist_find_client_by_id(server->local_list,
527 client_id, FALSE, NULL);
529 client = silc_idlist_find_client_by_id(server->global_list, client_id,
534 /* If router did not find such Client ID in its lists then this must
535 be bogus client or some router in the net is buggy. */
536 if (server->server_type != SILC_SERVER)
541 silc_parse_userfqdn(name, &nick, NULL);
543 /* We don't have that client anywhere, add it. The client is added
544 to global list since server didn't have it in the lists so it must be
546 client = silc_idlist_add_client(server->global_list, nick,
547 info ? strdup(info) : NULL, NULL,
548 client_id, cmd->sock->user_data,
549 NULL, time(NULL) + 300);
551 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
554 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
555 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
556 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
558 /* We have the client already, update the data */
560 SILC_LOG_DEBUG(("Updating client data"));
564 silc_parse_userfqdn(name, &nick, NULL);
566 /* Remove the old cache entry */
567 silc_idcache_del_by_context(global ? server->global_list->clients :
568 server->local_list->clients, client);
570 silc_free(client->nickname);
571 client->nickname = nick;
575 silc_free(client->username);
576 client->username = strdup(info);
579 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
580 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
583 /* Add new cache entry */
584 silc_idcache_add(global ? server->global_list->clients :
585 server->local_list->clients, nick, client->id,
586 client, expire, NULL);
589 /* If client is global and is not on any channel then add that we'll
590 expire the entry after a while. */
591 if (global && server->server_type == SILC_SERVER) {
592 SilcIDCacheEntry cache = NULL;
593 silc_idlist_find_client_by_id(server->global_list, client->id,
595 if (!silc_hash_table_count(client->channels))
596 cache->expire = time(NULL) + 300;
601 silc_free(client_id);
610 server_id = silc_id_payload_get_id(idp);
614 SILC_LOG_DEBUG(("Received server information"));
616 server_entry = silc_idlist_find_server_by_id(server->local_list,
617 server_id, FALSE, NULL);
619 server_entry = silc_idlist_find_server_by_id(server->global_list,
620 server_id, FALSE, NULL);
622 /* If router did not find such Server ID in its lists then this must
623 be bogus server or some router in the net is buggy. */
624 if (server->server_type != SILC_SERVER)
627 /* We don't have that server anywhere, add it. */
628 server_entry = silc_idlist_add_server(server->global_list,
630 server_id, server->router,
631 SILC_PRIMARY_ROUTE(server));
633 silc_free(server_id);
636 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
637 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
638 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
642 silc_free(server_id);
645 case SILC_ID_CHANNEL:
649 channel_id = silc_id_payload_get_id(idp);
653 SILC_LOG_DEBUG(("Received channel information"));
655 channel = silc_idlist_find_channel_by_name(server->local_list,
658 channel = silc_idlist_find_channel_by_name(server->global_list,
661 /* If router did not find such Channel ID in its lists then this must
662 be bogus channel or some router in the net is buggy. */
663 if (server->server_type != SILC_SERVER)
666 /* We don't have that channel anywhere, add it. */
667 channel = silc_idlist_add_channel(server->global_list, strdup(name),
668 SILC_CHANNEL_MODE_NONE, channel_id,
669 server->router, NULL, NULL, 0);
671 silc_free(channel_id);
677 silc_free(channel_id);
681 silc_id_payload_free(idp);
685 silc_id_payload_free(idp);
689 /* Received reply for forwarded IDENTIFY command. We have received the
690 requested identify information now and we will cache it. After this we
691 will call the pending command so that the requestee gets the information
694 SILC_SERVER_CMD_REPLY_FUNC(identify)
696 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
697 SilcStatus status, error;
699 COMMAND_CHECK_STATUS;
701 if (!silc_server_command_reply_identify_save(cmd))
704 /* Pending callbacks are not executed if this was an list entry */
705 if (status != SILC_STATUS_OK &&
706 status != SILC_STATUS_LIST_END) {
707 silc_server_command_reply_free(cmd);
712 silc_server_command_process_error(cmd, error);
713 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
714 silc_server_command_reply_free(cmd);
718 silc_server_command_process_error(cmd, error);
719 silc_server_command_reply_free(cmd);
722 /* Received reply fro INFO command. Cache the server and its information */
724 SILC_SERVER_CMD_REPLY_FUNC(info)
726 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
727 SilcServer server = cmd->server;
728 SilcStatus status, error;
729 SilcServerEntry entry;
730 SilcServerID *server_id;
732 unsigned char *tmp, *name;
734 COMMAND_CHECK_STATUS;
737 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
740 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
745 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
749 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
752 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
755 /* Add the server to global list */
756 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
757 entry = silc_idlist_add_server(server->global_list, name, 0,
758 server_id, cmd->sock->user_data,
761 silc_free(server_id);
764 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
768 /* Get the info string */
769 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
773 entry->server_info = tmp ? strdup(tmp) : NULL;
776 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
778 silc_server_command_reply_free(cmd);
781 /* Received reply fro MOTD command. */
783 SILC_SERVER_CMD_REPLY_FUNC(motd)
785 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
786 SilcServer server = cmd->server;
787 SilcStatus status, error;
788 SilcServerEntry entry = NULL;
789 SilcServerID *server_id;
793 COMMAND_CHECK_STATUS;
796 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
799 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
803 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
806 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
813 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
820 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
822 silc_server_command_reply_free(cmd);
828 /* Received reply for forwarded JOIN command. Router has created or joined
829 the client to the channel. We save some channel information locally
832 SILC_SERVER_CMD_REPLY_FUNC(join)
834 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
835 SilcServer server = cmd->server;
836 SilcIDCacheEntry cache = NULL;
837 SilcStatus status, error;
839 SilcClientID *client_id = NULL;
840 SilcChannelEntry entry;
841 SilcHmac hmac = NULL;
842 SilcUInt32 id_len, len, list_count;
843 unsigned char *id_string;
844 char *channel_name, *tmp;
845 SilcUInt32 mode, created;
846 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
847 SilcPublicKey founder_key = NULL;
849 COMMAND_CHECK_STATUS;
851 /* Get channel name */
852 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
857 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
862 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
865 client_id = silc_id_payload_parse_id(tmp, len, NULL);
870 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
873 SILC_GET32_MSB(mode, tmp);
875 /* Get created boolean value */
876 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
879 SILC_GET32_MSB(created, tmp);
880 if (created != 0 && created != 1)
883 /* Get channel key */
884 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
886 keyp = silc_buffer_alloc(len);
887 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
888 silc_buffer_put(keyp, tmp, len);
891 /* Parse the Channel ID */
892 id = silc_id_payload_parse_id(id_string, id_len, NULL);
897 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
899 if (!silc_hmac_alloc(tmp, NULL, &hmac))
903 /* Get the list count */
904 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
907 SILC_GET32_MSB(list_count, tmp);
909 /* Get Client ID list */
910 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
914 client_id_list = silc_buffer_alloc(len);
915 silc_buffer_pull_tail(client_id_list, len);
916 silc_buffer_put(client_id_list, tmp, len);
918 /* Get client mode list */
919 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
923 client_mode_list = silc_buffer_alloc(len);
924 silc_buffer_pull_tail(client_mode_list, len);
925 silc_buffer_put(client_mode_list, tmp, len);
927 /* Get founder key */
928 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
930 silc_pkcs_public_key_decode(tmp, len, &founder_key);
932 /* See whether we already have the channel. */
933 entry = silc_idlist_find_channel_by_name(server->local_list,
934 channel_name, &cache);
936 /* Add new channel */
938 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
939 (created == 0 ? "existing" : "created"), channel_name,
940 silc_id_render(id, SILC_ID_CHANNEL)));
942 /* If the channel is found from global list we must move it to the
944 entry = silc_idlist_find_channel_by_name(server->global_list,
945 channel_name, &cache);
947 silc_idlist_del_channel(server->global_list, entry);
949 /* Add the channel to our local list. */
950 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
951 SILC_CHANNEL_MODE_NONE, id,
952 server->router, NULL, hmac, 0);
957 server->stat.my_channels++;
958 server->stat.channels++;
960 /* The entry exists. */
962 /* If ID has changed, then update it to the cache too. */
963 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
964 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
966 entry->disabled = FALSE;
968 /* Remove the founder auth data if the mode is not set but we have
970 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
971 silc_pkcs_public_key_free(entry->founder_key);
972 entry->founder_key = NULL;
977 if (entry->founder_key)
978 silc_pkcs_public_key_free(entry->founder_key);
979 entry->founder_key = founder_key;
983 if (entry->hmac_name && hmac) {
984 silc_free(entry->hmac_name);
985 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
988 /* Get the ban list */
989 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
991 silc_free(entry->ban_list);
992 entry->ban_list = silc_memdup(tmp, len);
995 /* Get the invite list */
996 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
998 silc_free(entry->invite_list);
999 entry->invite_list = silc_memdup(tmp, len);
1003 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1005 silc_free(entry->topic);
1006 entry->topic = strdup(tmp);
1009 /* If channel was not created we know there is global users on the
1011 entry->global_users = (created == 0 ? TRUE : FALSE);
1013 /* If channel was just created the mask must be zero */
1014 if (!entry->global_users && mode) {
1015 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
1016 "new channel, forcing it to zero", cmd->sock->hostname));
1020 /* Save channel mode */
1023 /* Save channel key */
1025 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1026 silc_server_save_channel_key(server, keyp, entry);
1027 silc_buffer_free(keyp);
1030 /* Save the users to the channel */
1031 silc_server_save_users_on_channel(server, cmd->sock, entry,
1032 client_id, client_id_list,
1033 client_mode_list, list_count);
1034 entry->users_resolved = TRUE;
1037 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1039 silc_free(client_id);
1040 silc_server_command_reply_free(cmd);
1042 silc_pkcs_public_key_free(founder_key);
1044 silc_buffer_free(client_id_list);
1045 if (client_mode_list)
1046 silc_buffer_free(client_mode_list);
1049 /* Received reply to STATS command. */
1051 SILC_SERVER_CMD_REPLY_FUNC(stats)
1053 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1054 SilcServer server = cmd->server;
1055 SilcStatus status, error;
1058 SilcBufferStruct buf;
1060 COMMAND_CHECK_STATUS;
1062 /* Get statistics structure */
1063 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1064 if (server->server_type == SILC_SERVER && tmp) {
1065 silc_buffer_set(&buf, tmp, tmp_len);
1066 silc_buffer_unformat(&buf,
1067 SILC_STR_UI_INT(NULL),
1068 SILC_STR_UI_INT(NULL),
1069 SILC_STR_UI_INT(NULL),
1070 SILC_STR_UI_INT(NULL),
1071 SILC_STR_UI_INT(NULL),
1072 SILC_STR_UI_INT(NULL),
1073 SILC_STR_UI_INT(&server->stat.cell_clients),
1074 SILC_STR_UI_INT(&server->stat.cell_channels),
1075 SILC_STR_UI_INT(&server->stat.cell_servers),
1076 SILC_STR_UI_INT(&server->stat.clients),
1077 SILC_STR_UI_INT(&server->stat.channels),
1078 SILC_STR_UI_INT(&server->stat.servers),
1079 SILC_STR_UI_INT(&server->stat.routers),
1080 SILC_STR_UI_INT(&server->stat.server_ops),
1081 SILC_STR_UI_INT(&server->stat.router_ops),
1086 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1088 silc_server_command_reply_free(cmd);
1091 SILC_SERVER_CMD_REPLY_FUNC(users)
1093 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1094 SilcServer server = cmd->server;
1095 SilcStatus status, error;
1096 SilcChannelEntry channel;
1097 SilcChannelID *channel_id = NULL;
1098 SilcBuffer client_id_list;
1099 SilcBuffer client_mode_list;
1102 SilcUInt32 list_count;
1104 COMMAND_CHECK_STATUS;
1106 /* Get channel ID */
1107 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1110 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1114 /* Get channel entry */
1115 channel = silc_idlist_find_channel_by_id(server->local_list,
1118 channel = silc_idlist_find_channel_by_id(server->global_list,
1123 if (server->server_type != SILC_SERVER)
1126 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1127 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1128 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1129 1, 5, idp->data, idp->len);
1130 silc_buffer_free(idp);
1132 /* Register pending command callback. After we've received the channel
1133 information we will reprocess this command reply by re-calling this
1134 USERS command reply callback. */
1135 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1137 silc_server_command_reply_users, cmd);
1142 /* Get the list count */
1143 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1146 SILC_GET32_MSB(list_count, tmp);
1148 /* Get Client ID list */
1149 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1153 client_id_list = silc_buffer_alloc(tmp_len);
1154 silc_buffer_pull_tail(client_id_list, tmp_len);
1155 silc_buffer_put(client_id_list, tmp, tmp_len);
1157 /* Get client mode list */
1158 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1162 client_mode_list = silc_buffer_alloc(tmp_len);
1163 silc_buffer_pull_tail(client_mode_list, tmp_len);
1164 silc_buffer_put(client_mode_list, tmp, tmp_len);
1166 /* Save the users to the channel */
1167 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1168 client_id_list, client_mode_list,
1171 channel->global_users = silc_server_channel_has_global(channel);
1172 channel->users_resolved = TRUE;
1174 silc_buffer_free(client_id_list);
1175 silc_buffer_free(client_mode_list);
1178 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1179 silc_free(channel_id);
1181 silc_server_command_reply_free(cmd);
1184 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1186 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1187 SilcServer server = cmd->server;
1188 SilcStatus status, error;
1189 SilcClientEntry client = NULL;
1190 SilcServerEntry server_entry = NULL;
1191 SilcClientID *client_id = NULL;
1192 SilcServerID *server_id = NULL;
1194 unsigned char *tmp, *pk;
1197 SilcIDPayload idp = NULL;
1199 SilcPublicKey public_key = NULL;
1201 COMMAND_CHECK_STATUS;
1203 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1206 idp = silc_id_payload_parse(tmp, len);
1210 /* Get the public key payload */
1211 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1215 /* Decode the public key */
1217 SILC_GET16_MSB(pk_len, tmp);
1218 SILC_GET16_MSB(type, tmp + 2);
1221 if (type != SILC_SKE_PK_TYPE_SILC)
1224 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1227 id_type = silc_id_payload_get_type(idp);
1228 if (id_type == SILC_ID_CLIENT) {
1229 client_id = silc_id_payload_get_id(idp);
1231 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1234 client = silc_idlist_find_client_by_id(server->global_list,
1235 client_id, TRUE, NULL);
1240 client->data.public_key = public_key;
1242 } else if (id_type == SILC_ID_SERVER) {
1243 server_id = silc_id_payload_get_id(idp);
1245 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1247 if (!server_entry) {
1248 server_entry = silc_idlist_find_server_by_id(server->global_list,
1249 server_id, TRUE, NULL);
1254 server_entry->data.public_key = public_key;
1261 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1263 silc_id_payload_free(idp);
1264 silc_free(client_id);
1265 silc_free(server_id);
1267 silc_pkcs_public_key_free(public_key);
1269 silc_server_command_reply_free(cmd);
1272 SILC_SERVER_CMD_REPLY_FUNC(list)
1274 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1275 SilcServer server = cmd->server;
1276 SilcStatus status, error;
1277 SilcChannelID *channel_id = NULL;
1278 SilcChannelEntry channel;
1279 SilcIDCacheEntry cache;
1281 unsigned char *tmp, *name, *topic;
1282 SilcUInt32 usercount = 0;
1283 bool global_list = FALSE;
1285 COMMAND_CHECK_STATUS;
1287 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1288 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1292 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1293 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1294 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1296 SILC_GET32_MSB(usercount, tmp);
1298 /* Add the channel entry if we do not have it already */
1299 channel = silc_idlist_find_channel_by_name(server->local_list,
1302 channel = silc_idlist_find_channel_by_name(server->global_list,
1307 /* If router did not find such channel in its lists then this must
1308 be bogus channel or some router in the net is buggy. */
1309 if (server->server_type != SILC_SERVER)
1312 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1313 SILC_CHANNEL_MODE_NONE, channel_id,
1314 server->router, NULL, NULL,
1320 /* Found, update expiry */
1321 if (global_list && server->server_type == SILC_SERVER)
1322 cache->expire = time(NULL) + 60;
1325 channel->user_count = usercount;
1328 silc_free(channel->topic);
1329 channel->topic = strdup(topic);
1332 /* Pending callbacks are not executed if this was an list entry */
1333 if (status != SILC_STATUS_OK &&
1334 status != SILC_STATUS_LIST_END) {
1335 silc_server_command_reply_free(cmd);
1339 /* Now purge all old entries from the global list, otherwise we'll might
1340 have non-existent entries for long periods of time in the cache. */
1341 silc_idcache_purge(server->global_list->channels);
1344 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1345 silc_free(channel_id);
1347 silc_server_command_reply_free(cmd);
1350 SILC_SERVER_CMD_REPLY_FUNC(watch)
1352 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1353 SilcStatus status, error;
1355 COMMAND_CHECK_STATUS;
1358 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1360 silc_server_command_reply_free(cmd);