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 /* Reiceved reply for WHOIS command. We sent the whois request to our
294 primary router, if we are normal server, and thus has now received reply
295 to the command. We will figure out what client originally sent us the
296 command and will send the reply to it. If we are router we will figure
297 out who server sent us the command and send reply to that one. */
299 SILC_SERVER_CMD_REPLY_FUNC(whois)
301 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
302 SilcStatus status, error;
304 COMMAND_CHECK_STATUS;
306 if (!silc_server_command_reply_whois_save(cmd))
309 /* Pending callbacks are not executed if this was an list entry */
310 if (status != SILC_STATUS_OK &&
311 status != SILC_STATUS_LIST_END) {
312 silc_server_command_reply_free(cmd);
317 silc_server_command_process_error(cmd, error);
318 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
319 silc_server_command_reply_free(cmd);
323 silc_server_command_process_error(cmd, error);
324 silc_server_command_reply_free(cmd);
327 /* Caches the received WHOWAS information for a short period of time. */
330 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
332 SilcServer server = cmd->server;
333 SilcUInt32 len, id_len;
334 unsigned char *id_data;
335 char *nickname, *username, *realname, *servername = NULL;
336 SilcClientID *client_id;
337 SilcClientEntry client;
338 SilcIDCacheEntry cache = NULL;
342 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
343 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
344 username = silc_argument_get_arg_type(cmd->args, 4, &len);
345 if (!id_data || !nickname || !username)
348 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
350 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
354 /* Check if we have this client cached already. */
356 client = silc_idlist_find_client_by_id(server->local_list, client_id,
359 client = silc_idlist_find_client_by_id(server->global_list,
360 client_id, FALSE, &cache);
365 /* If router did not find such Client ID in its lists then this must
366 be bogus client or some router in the net is buggy. */
367 if (server->server_type != SILC_SERVER)
370 /* Take hostname out of nick string if it includes it. */
371 silc_parse_userfqdn(nickname, &nick, &servername);
373 /* We don't have that client anywhere, add it. The client is added
374 to global list since server didn't have it in the lists so it must be
376 client = silc_idlist_add_client(server->global_list, nick,
377 strdup(username), strdup(realname),
378 silc_id_dup(client_id, SILC_ID_CLIENT),
379 cmd->sock->user_data, NULL,
380 SILC_ID_CACHE_EXPIRE_DEF);
382 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
386 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
387 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
388 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
389 client->servername = servername;
391 /* We have the client already, update the data */
393 /* Take hostname out of nick string if it includes it. */
394 silc_parse_userfqdn(nickname, &nick, &servername);
396 silc_free(client->nickname);
397 silc_free(client->username);
398 silc_free(client->servername);
400 client->nickname = nick;
401 client->username = strdup(username);
402 client->servername = servername;
403 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
404 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
406 /* Remove the old cache entry and create a new one */
407 silc_idcache_del_by_context(global ? server->global_list->clients :
408 server->local_list->clients, client);
409 silc_idcache_add(global ? server->global_list->clients :
410 server->local_list->clients, nick, client->id,
414 /* If client is global and is not on any channel then add that we'll
415 expire the entry after a while. */
417 silc_idlist_find_client_by_id(server->global_list, client->id,
419 if (!silc_hash_table_count(client->channels))
420 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
425 silc_free(client_id);
430 /* Received reply for WHOWAS command. Cache the client information only for
431 a short period of time. */
433 SILC_SERVER_CMD_REPLY_FUNC(whowas)
435 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
436 SilcStatus status, error;
438 COMMAND_CHECK_STATUS;
440 if (!silc_server_command_reply_whowas_save(cmd))
443 /* Pending callbacks are not executed if this was an list entry */
444 if (status != SILC_STATUS_OK &&
445 status != SILC_STATUS_LIST_END) {
446 silc_server_command_reply_free(cmd);
451 silc_server_command_process_error(cmd, error);
452 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
453 silc_server_command_reply_free(cmd);
457 silc_server_command_process_error(cmd, error);
458 silc_server_command_reply_free(cmd);
461 /* Caches the received IDENTIFY information. */
464 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
466 SilcServer server = cmd->server;
467 SilcUInt32 len, id_len;
468 unsigned char *id_data;
470 SilcClientID *client_id = NULL;
471 SilcServerID *server_id = NULL;
472 SilcChannelID *channel_id = NULL;
473 SilcClientEntry client;
474 SilcServerEntry server_entry;
475 SilcChannelEntry channel;
478 SilcIDPayload idp = NULL;
482 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
485 idp = silc_id_payload_parse(id_data, id_len);
489 name = silc_argument_get_arg_type(cmd->args, 3, &len);
490 info = silc_argument_get_arg_type(cmd->args, 4, &len);
492 id_type = silc_id_payload_get_type(idp);
496 client_id = silc_id_payload_get_id(idp);
500 SILC_LOG_DEBUG(("Received client information"));
502 client = silc_idlist_find_client_by_id(server->local_list,
503 client_id, FALSE, NULL);
505 client = silc_idlist_find_client_by_id(server->global_list, client_id,
510 /* If router did not find such Client ID in its lists then this must
511 be bogus client or some router in the net is buggy. */
512 if (server->server_type != SILC_SERVER)
517 silc_parse_userfqdn(name, &nick, NULL);
519 /* We don't have that client anywhere, add it. The client is added
520 to global list since server didn't have it in the lists so it must be
522 client = silc_idlist_add_client(server->global_list, nick,
523 info ? strdup(info) : NULL, NULL,
524 client_id, cmd->sock->user_data,
525 NULL, time(NULL) + 300);
527 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
530 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
531 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
532 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
534 /* We have the client already, update the data */
536 SILC_LOG_DEBUG(("Updating client data"));
540 silc_parse_userfqdn(name, &nick, NULL);
542 /* Remove the old cache entry */
543 silc_idcache_del_by_context(global ? server->global_list->clients :
544 server->local_list->clients, client);
546 silc_free(client->nickname);
547 client->nickname = nick;
551 silc_free(client->username);
552 client->username = strdup(info);
555 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
556 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
559 /* Add new cache entry */
560 silc_idcache_add(global ? server->global_list->clients :
561 server->local_list->clients, nick, client->id,
562 client, expire, NULL);
565 /* If client is global and is not on any channel then add that we'll
566 expire the entry after a while. */
567 if (global && server->server_type == SILC_SERVER) {
568 SilcIDCacheEntry cache = NULL;
569 silc_idlist_find_client_by_id(server->global_list, client->id,
571 if (!silc_hash_table_count(client->channels))
572 cache->expire = time(NULL) + 300;
577 silc_free(client_id);
586 server_id = silc_id_payload_get_id(idp);
590 SILC_LOG_DEBUG(("Received server information"));
592 server_entry = silc_idlist_find_server_by_id(server->local_list,
593 server_id, FALSE, NULL);
595 server_entry = silc_idlist_find_server_by_id(server->global_list,
596 server_id, FALSE, NULL);
598 /* If router did not find such Server ID in its lists then this must
599 be bogus server or some router in the net is buggy. */
600 if (server->server_type != SILC_SERVER)
603 /* We don't have that server anywhere, add it. */
604 server_entry = silc_idlist_add_server(server->global_list,
606 server_id, server->router,
607 SILC_PRIMARY_ROUTE(server));
609 silc_free(server_id);
612 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
613 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
614 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
618 silc_free(server_id);
621 case SILC_ID_CHANNEL:
625 channel_id = silc_id_payload_get_id(idp);
629 SILC_LOG_DEBUG(("Received channel information"));
631 channel = silc_idlist_find_channel_by_name(server->local_list,
634 channel = silc_idlist_find_channel_by_name(server->global_list,
637 /* If router did not find such Channel ID in its lists then this must
638 be bogus channel or some router in the net is buggy. */
639 if (server->server_type != SILC_SERVER)
642 /* We don't have that channel anywhere, add it. */
643 channel = silc_idlist_add_channel(server->global_list, strdup(name),
644 SILC_CHANNEL_MODE_NONE, channel_id,
645 server->router, NULL, NULL, 0);
647 silc_free(channel_id);
653 silc_free(channel_id);
657 silc_id_payload_free(idp);
661 silc_id_payload_free(idp);
665 /* Received reply for forwarded IDENTIFY command. We have received the
666 requested identify information now and we will cache it. After this we
667 will call the pending command so that the requestee gets the information
670 SILC_SERVER_CMD_REPLY_FUNC(identify)
672 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
673 SilcStatus status, error;
675 COMMAND_CHECK_STATUS;
677 if (!silc_server_command_reply_identify_save(cmd))
680 /* Pending callbacks are not executed if this was an list entry */
681 if (status != SILC_STATUS_OK &&
682 status != SILC_STATUS_LIST_END) {
683 silc_server_command_reply_free(cmd);
688 silc_server_command_process_error(cmd, error);
689 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
690 silc_server_command_reply_free(cmd);
694 silc_server_command_process_error(cmd, error);
695 silc_server_command_reply_free(cmd);
698 /* Received reply fro INFO command. Cache the server and its information */
700 SILC_SERVER_CMD_REPLY_FUNC(info)
702 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
703 SilcServer server = cmd->server;
704 SilcStatus status, error;
705 SilcServerEntry entry;
706 SilcServerID *server_id;
708 unsigned char *tmp, *name;
710 COMMAND_CHECK_STATUS;
713 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
716 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
721 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
725 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
728 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
731 /* Add the server to global list */
732 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
733 entry = silc_idlist_add_server(server->global_list, name, 0,
734 server_id, cmd->sock->user_data,
737 silc_free(server_id);
740 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
744 /* Get the info string */
745 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
749 entry->server_info = tmp ? strdup(tmp) : NULL;
752 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
754 silc_server_command_reply_free(cmd);
757 /* Received reply fro MOTD command. */
759 SILC_SERVER_CMD_REPLY_FUNC(motd)
761 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
762 SilcServer server = cmd->server;
763 SilcStatus status, error;
764 SilcServerEntry entry = NULL;
765 SilcServerID *server_id;
769 COMMAND_CHECK_STATUS;
772 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
775 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
779 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
782 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
789 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
796 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
798 silc_server_command_reply_free(cmd);
804 /* Received reply for forwarded JOIN command. Router has created or joined
805 the client to the channel. We save some channel information locally
808 SILC_SERVER_CMD_REPLY_FUNC(join)
810 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
811 SilcServer server = cmd->server;
812 SilcIDCacheEntry cache = NULL;
813 SilcStatus status, error;
815 SilcClientID *client_id = NULL;
816 SilcChannelEntry entry;
817 SilcHmac hmac = NULL;
818 SilcUInt32 id_len, len, list_count;
819 unsigned char *id_string;
820 char *channel_name, *tmp;
821 SilcUInt32 mode, created;
822 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
823 SilcPublicKey founder_key = NULL;
825 COMMAND_CHECK_STATUS;
827 /* Get channel name */
828 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
833 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
838 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
841 client_id = silc_id_payload_parse_id(tmp, len, NULL);
846 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
849 SILC_GET32_MSB(mode, tmp);
851 /* Get created boolean value */
852 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
855 SILC_GET32_MSB(created, tmp);
856 if (created != 0 && created != 1)
859 /* Get channel key */
860 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
862 keyp = silc_buffer_alloc(len);
863 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
864 silc_buffer_put(keyp, tmp, len);
867 /* Parse the Channel ID */
868 id = silc_id_payload_parse_id(id_string, id_len, NULL);
873 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
875 if (!silc_hmac_alloc(tmp, NULL, &hmac))
879 /* Get the list count */
880 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
883 SILC_GET32_MSB(list_count, tmp);
885 /* Get Client ID list */
886 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
890 client_id_list = silc_buffer_alloc(len);
891 silc_buffer_pull_tail(client_id_list, len);
892 silc_buffer_put(client_id_list, tmp, len);
894 /* Get client mode list */
895 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
899 client_mode_list = silc_buffer_alloc(len);
900 silc_buffer_pull_tail(client_mode_list, len);
901 silc_buffer_put(client_mode_list, tmp, len);
903 /* Get founder key */
904 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
906 silc_pkcs_public_key_decode(tmp, len, &founder_key);
908 /* See whether we already have the channel. */
909 entry = silc_idlist_find_channel_by_name(server->local_list,
910 channel_name, &cache);
912 /* Add new channel */
914 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
915 (created == 0 ? "existing" : "created"), channel_name,
916 silc_id_render(id, SILC_ID_CHANNEL)));
918 /* If the channel is found from global list we must move it to the
920 entry = silc_idlist_find_channel_by_name(server->global_list,
921 channel_name, &cache);
923 silc_idlist_del_channel(server->global_list, entry);
925 /* Add the channel to our local list. */
926 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
927 SILC_CHANNEL_MODE_NONE, id,
928 server->router, NULL, hmac, 0);
933 server->stat.my_channels++;
934 server->stat.channels++;
936 /* The entry exists. */
938 /* If ID has changed, then update it to the cache too. */
939 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
940 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
942 entry->disabled = FALSE;
944 /* Remove the founder auth data if the mode is not set but we have
946 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
947 silc_pkcs_public_key_free(entry->founder_key);
948 entry->founder_key = NULL;
953 if (entry->founder_key)
954 silc_pkcs_public_key_free(entry->founder_key);
955 entry->founder_key = founder_key;
959 if (entry->hmac_name && hmac) {
960 silc_free(entry->hmac_name);
961 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
964 /* Get the ban list */
965 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
967 silc_free(entry->ban_list);
968 entry->ban_list = silc_memdup(tmp, len);
971 /* Get the invite list */
972 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
974 silc_free(entry->invite_list);
975 entry->invite_list = silc_memdup(tmp, len);
979 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
981 silc_free(entry->topic);
982 entry->topic = strdup(tmp);
985 /* If channel was not created we know there is global users on the
987 entry->global_users = (created == 0 ? TRUE : FALSE);
989 /* If channel was just created the mask must be zero */
990 if (!entry->global_users && mode) {
991 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
992 "new channel, forcing it to zero", cmd->sock->hostname));
996 /* Save channel mode */
999 /* Save channel key */
1001 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1002 silc_server_save_channel_key(server, keyp, entry);
1003 silc_buffer_free(keyp);
1006 /* Save the users to the channel */
1007 silc_server_save_users_on_channel(server, cmd->sock, entry,
1008 client_id, client_id_list,
1009 client_mode_list, list_count);
1010 entry->users_resolved = TRUE;
1013 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1015 silc_free(client_id);
1016 silc_server_command_reply_free(cmd);
1018 silc_pkcs_public_key_free(founder_key);
1020 silc_buffer_free(client_id_list);
1021 if (client_mode_list)
1022 silc_buffer_free(client_mode_list);
1025 /* Received reply to STATS command. */
1027 SILC_SERVER_CMD_REPLY_FUNC(stats)
1029 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1030 SilcServer server = cmd->server;
1031 SilcStatus status, error;
1034 SilcBufferStruct buf;
1036 COMMAND_CHECK_STATUS;
1038 /* Get statistics structure */
1039 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1040 if (server->server_type == SILC_SERVER && tmp) {
1041 silc_buffer_set(&buf, tmp, tmp_len);
1042 silc_buffer_unformat(&buf,
1043 SILC_STR_UI_INT(NULL),
1044 SILC_STR_UI_INT(NULL),
1045 SILC_STR_UI_INT(NULL),
1046 SILC_STR_UI_INT(NULL),
1047 SILC_STR_UI_INT(NULL),
1048 SILC_STR_UI_INT(NULL),
1049 SILC_STR_UI_INT(&server->stat.cell_clients),
1050 SILC_STR_UI_INT(&server->stat.cell_channels),
1051 SILC_STR_UI_INT(&server->stat.cell_servers),
1052 SILC_STR_UI_INT(&server->stat.clients),
1053 SILC_STR_UI_INT(&server->stat.channels),
1054 SILC_STR_UI_INT(&server->stat.servers),
1055 SILC_STR_UI_INT(&server->stat.routers),
1056 SILC_STR_UI_INT(&server->stat.server_ops),
1057 SILC_STR_UI_INT(&server->stat.router_ops),
1062 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1064 silc_server_command_reply_free(cmd);
1067 SILC_SERVER_CMD_REPLY_FUNC(users)
1069 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1070 SilcServer server = cmd->server;
1071 SilcStatus status, error;
1072 SilcChannelEntry channel;
1073 SilcChannelID *channel_id = NULL;
1074 SilcBuffer client_id_list;
1075 SilcBuffer client_mode_list;
1078 SilcUInt32 list_count;
1080 COMMAND_CHECK_STATUS;
1082 /* Get channel ID */
1083 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1086 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1090 /* Get channel entry */
1091 channel = silc_idlist_find_channel_by_id(server->local_list,
1094 channel = silc_idlist_find_channel_by_id(server->global_list,
1099 if (server->server_type != SILC_SERVER)
1102 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1103 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1104 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1105 1, 5, idp->data, idp->len);
1106 silc_buffer_free(idp);
1108 /* Register pending command callback. After we've received the channel
1109 information we will reprocess this command reply by re-calling this
1110 USERS command reply callback. */
1111 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1113 silc_server_command_reply_users, cmd);
1118 /* Get the list count */
1119 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1122 SILC_GET32_MSB(list_count, tmp);
1124 /* Get Client ID list */
1125 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1129 client_id_list = silc_buffer_alloc(tmp_len);
1130 silc_buffer_pull_tail(client_id_list, tmp_len);
1131 silc_buffer_put(client_id_list, tmp, tmp_len);
1133 /* Get client mode list */
1134 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1138 client_mode_list = silc_buffer_alloc(tmp_len);
1139 silc_buffer_pull_tail(client_mode_list, tmp_len);
1140 silc_buffer_put(client_mode_list, tmp, tmp_len);
1142 /* Save the users to the channel */
1143 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1144 client_id_list, client_mode_list,
1147 channel->global_users = silc_server_channel_has_global(channel);
1148 channel->users_resolved = TRUE;
1150 silc_buffer_free(client_id_list);
1151 silc_buffer_free(client_mode_list);
1154 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1155 silc_free(channel_id);
1157 silc_server_command_reply_free(cmd);
1160 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1162 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1163 SilcServer server = cmd->server;
1164 SilcStatus status, error;
1165 SilcClientEntry client = NULL;
1166 SilcServerEntry server_entry = NULL;
1167 SilcClientID *client_id = NULL;
1168 SilcServerID *server_id = NULL;
1170 unsigned char *tmp, *pk;
1173 SilcIDPayload idp = NULL;
1175 SilcPublicKey public_key = NULL;
1177 COMMAND_CHECK_STATUS;
1179 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1182 idp = silc_id_payload_parse(tmp, len);
1186 /* Get the public key payload */
1187 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1191 /* Decode the public key */
1193 SILC_GET16_MSB(pk_len, tmp);
1194 SILC_GET16_MSB(type, tmp + 2);
1197 if (type != SILC_SKE_PK_TYPE_SILC)
1200 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1203 id_type = silc_id_payload_get_type(idp);
1204 if (id_type == SILC_ID_CLIENT) {
1205 client_id = silc_id_payload_get_id(idp);
1207 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1210 client = silc_idlist_find_client_by_id(server->global_list,
1211 client_id, TRUE, NULL);
1216 client->data.public_key = public_key;
1218 } else if (id_type == SILC_ID_SERVER) {
1219 server_id = silc_id_payload_get_id(idp);
1221 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1223 if (!server_entry) {
1224 server_entry = silc_idlist_find_server_by_id(server->global_list,
1225 server_id, TRUE, NULL);
1230 server_entry->data.public_key = public_key;
1237 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1239 silc_id_payload_free(idp);
1240 silc_free(client_id);
1241 silc_free(server_id);
1243 silc_pkcs_public_key_free(public_key);
1245 silc_server_command_reply_free(cmd);
1248 SILC_SERVER_CMD_REPLY_FUNC(list)
1250 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1251 SilcServer server = cmd->server;
1252 SilcStatus status, error;
1253 SilcChannelID *channel_id = NULL;
1254 SilcChannelEntry channel;
1255 SilcIDCacheEntry cache;
1257 unsigned char *tmp, *name, *topic;
1258 SilcUInt32 usercount = 0;
1259 bool global_list = FALSE;
1261 COMMAND_CHECK_STATUS;
1263 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1264 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1268 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1269 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1270 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1272 SILC_GET32_MSB(usercount, tmp);
1274 /* Add the channel entry if we do not have it already */
1275 channel = silc_idlist_find_channel_by_name(server->local_list,
1278 channel = silc_idlist_find_channel_by_name(server->global_list,
1283 /* If router did not find such channel in its lists then this must
1284 be bogus channel or some router in the net is buggy. */
1285 if (server->server_type != SILC_SERVER)
1288 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1289 SILC_CHANNEL_MODE_NONE, channel_id,
1290 server->router, NULL, NULL,
1296 /* Found, update expiry */
1297 if (global_list && server->server_type == SILC_SERVER)
1298 cache->expire = time(NULL) + 60;
1301 channel->user_count = usercount;
1304 silc_free(channel->topic);
1305 channel->topic = strdup(topic);
1308 /* Pending callbacks are not executed if this was an list entry */
1309 if (status != SILC_STATUS_OK &&
1310 status != SILC_STATUS_LIST_END) {
1311 silc_server_command_reply_free(cmd);
1315 /* Now purge all old entries from the global list, otherwise we'll might
1316 have non-existent entries for long periods of time in the cache. */
1317 silc_idcache_purge(server->global_list->channels);
1320 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1321 silc_free(channel_id);
1323 silc_server_command_reply_free(cmd);
1326 SILC_SERVER_CMD_REPLY_FUNC(watch)
1328 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1329 SilcStatus status, error;
1331 COMMAND_CHECK_STATUS;
1334 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1336 silc_server_command_reply_free(cmd);