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),
55 SILC_SERVER_CMD_REPLY(watch, WATCH),
60 /* Process received command reply. */
62 void silc_server_command_reply_process(SilcServer server,
63 SilcSocketConnection sock,
66 SilcServerCommandReply *cmd;
67 SilcServerCommandReplyContext ctx;
68 SilcCommandPayload payload;
71 SILC_LOG_DEBUG(("Start"));
73 /* Get command reply payload from packet */
74 payload = silc_command_payload_parse(buffer->data, buffer->len);
76 /* Silently ignore bad reply packet */
77 SILC_LOG_DEBUG(("Bad command reply packet"));
81 /* Allocate command reply context. This must be free'd by the
82 command reply routine receiving it. */
83 ctx = silc_calloc(1, sizeof(*ctx));
85 ctx->sock = silc_socket_dup(sock);
86 ctx->payload = payload;
87 ctx->args = silc_command_get_args(ctx->payload);
88 ctx->ident = silc_command_get_ident(ctx->payload);
89 command = silc_command_get(ctx->payload);
91 /* Client is not allowed to send reply to all commands */
92 if (sock->type == SILC_SOCKET_TYPE_CLIENT &&
93 command != SILC_COMMAND_WHOIS) {
94 silc_server_command_reply_free(ctx);
98 /* Check for pending commands and mark to be exeucted */
100 silc_server_command_pending_check(server, command,
101 ctx->ident, &ctx->callbacks_count);
103 /* Execute command reply */
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);
130 silc_server_command_process_error(SilcServerCommandReplyContext cmd,
133 SilcServer server = cmd->server;
135 /* If we received notify for invalid ID we'll remove the ID if we
137 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
138 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
139 SilcClientEntry client;
141 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
143 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
145 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
146 "the entry from cache"));
147 client = silc_idlist_find_client_by_id(server->global_list,
148 client_id, FALSE, NULL);
150 silc_server_remove_from_channels(server, NULL, client, TRUE,
152 silc_idlist_del_data(client);
153 silc_idlist_del_client(server->global_list, client);
155 silc_free(client_id);
161 /* Caches the received WHOIS information. */
164 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
166 SilcServer server = cmd->server;
167 unsigned char *tmp, *id_data, *umodes;
168 char *nickname, *username, *realname, *servername = NULL;
169 unsigned char *fingerprint;
170 SilcClientID *client_id;
171 SilcClientEntry client;
172 SilcIDCacheEntry cache = NULL;
175 SilcUInt32 mode = 0, len, len2, id_len, flen;
177 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
178 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
179 username = silc_argument_get_arg_type(cmd->args, 4, &len);
180 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
181 if (!id_data || !nickname || !username || !realname)
184 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
186 SILC_GET32_MSB(mode, tmp);
188 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
192 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
194 /* Check if we have this client cached already. */
196 client = silc_idlist_find_client_by_id(server->local_list, client_id,
199 client = silc_idlist_find_client_by_id(server->global_list, client_id,
205 /* If router did not find such Client ID in its lists then this must
206 be bogus client or some router in the net is buggy. */
207 if (server->server_type != SILC_SERVER)
210 /* Take hostname out of nick string if it includes it. */
211 silc_parse_userfqdn(nickname, &nick, &servername);
213 /* We don't have that client anywhere, add it. The client is added
214 to global list since server didn't have it in the lists so it must be
216 client = silc_idlist_add_client(server->global_list, nick,
218 strdup(realname), client_id,
219 cmd->sock->user_data, NULL, 0);
221 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
225 client->data.status |=
226 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
227 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
229 client->servername = servername;
231 /* We have the client already, update the data */
233 SILC_LOG_DEBUG(("Updating client data"));
235 /* Take hostname out of nick string if it includes it. */
236 silc_parse_userfqdn(nickname, &nick, &servername);
238 /* Remove the old cache entry */
239 silc_idcache_del_by_context(global ? server->global_list->clients :
240 server->local_list->clients, client);
242 silc_free(client->nickname);
243 silc_free(client->username);
244 silc_free(client->userinfo);
245 silc_free(client->servername);
247 client->nickname = nick;
248 client->username = strdup(username);
249 client->userinfo = strdup(realname);
250 client->servername = servername;
252 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
253 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
255 /* Create new cache entry */
256 silc_idcache_add(global ? server->global_list->clients :
257 server->local_list->clients, nick, client->id,
259 silc_free(client_id);
262 /* Save channel list if it was sent to us */
263 if (server->server_type == SILC_SERVER) {
264 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
265 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
267 SilcBufferStruct channels_buf, umodes_buf;
268 silc_buffer_set(&channels_buf, tmp, len);
269 silc_buffer_set(&umodes_buf, umodes, len2);
270 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
273 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
276 /* If client is global and is not on any channel then add that we'll
277 expire the entry after a while. */
279 silc_idlist_find_client_by_id(server->global_list, client->id,
281 if (!silc_hash_table_count(client->channels))
282 cache->expire = time(NULL) + 300;
288 if (fingerprint && flen == sizeof(client->data.fingerprint))
289 memcpy(client->data.fingerprint, fingerprint, flen);
291 /* Take Requested Attributes if set. */
292 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
294 silc_free(client->attrs);
295 client->attrs = silc_memdup(tmp, len);
296 client->attrs_len = len;
302 /* Handle requested attributes reply in WHOIS from client */
305 silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd)
309 SilcClientEntry client = cmd->sock->user_data;
311 /* Take Requested Attributes if set. */
312 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
314 silc_free(client->attrs);
315 client->attrs = silc_memdup(tmp, len);
316 client->attrs_len = len;
319 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
324 /* Reiceved reply for WHOIS command. We sent the whois request to our
325 primary router, if we are normal server, and thus has now received reply
326 to the command. We will figure out what client originally sent us the
327 command and will send the reply to it. If we are router we will figure
328 out who server sent us the command and send reply to that one. */
330 SILC_SERVER_CMD_REPLY_FUNC(whois)
332 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
333 SilcStatus status, error;
335 COMMAND_CHECK_STATUS;
337 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) {
338 if (!silc_server_command_reply_whois_save(cmd))
341 if (!silc_server_command_reply_whois_save_client(cmd))
345 /* Pending callbacks are not executed if this was an list entry */
346 if (status != SILC_STATUS_OK &&
347 status != SILC_STATUS_LIST_END) {
348 silc_server_command_reply_free(cmd);
353 silc_server_command_process_error(cmd, error);
354 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
355 silc_server_command_reply_free(cmd);
359 silc_server_command_process_error(cmd, error);
360 silc_server_command_reply_free(cmd);
363 /* Caches the received WHOWAS information for a short period of time. */
366 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
368 SilcServer server = cmd->server;
369 SilcUInt32 len, id_len;
370 unsigned char *id_data;
371 char *nickname, *username, *realname, *servername = NULL;
372 SilcClientID *client_id;
373 SilcClientEntry client;
374 SilcIDCacheEntry cache = NULL;
378 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
379 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
380 username = silc_argument_get_arg_type(cmd->args, 4, &len);
381 if (!id_data || !nickname || !username)
384 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
386 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
390 /* Check if we have this client cached already. */
392 client = silc_idlist_find_client_by_id(server->local_list, client_id,
395 client = silc_idlist_find_client_by_id(server->global_list,
396 client_id, FALSE, &cache);
401 /* If router did not find such Client ID in its lists then this must
402 be bogus client or some router in the net is buggy. */
403 if (server->server_type != SILC_SERVER)
406 /* Take hostname out of nick string if it includes it. */
407 silc_parse_userfqdn(nickname, &nick, &servername);
409 /* We don't have that client anywhere, add it. The client is added
410 to global list since server didn't have it in the lists so it must be
412 client = silc_idlist_add_client(server->global_list, nick,
413 strdup(username), strdup(realname),
414 silc_id_dup(client_id, SILC_ID_CLIENT),
415 cmd->sock->user_data, NULL,
416 SILC_ID_CACHE_EXPIRE_DEF);
418 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
422 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
423 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
424 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
425 client->servername = servername;
427 /* We have the client already, update the data */
429 /* Take hostname out of nick string if it includes it. */
430 silc_parse_userfqdn(nickname, &nick, &servername);
432 silc_free(client->nickname);
433 silc_free(client->username);
434 silc_free(client->servername);
436 client->nickname = nick;
437 client->username = strdup(username);
438 client->servername = servername;
439 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
440 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
442 /* Remove the old cache entry and create a new one */
443 silc_idcache_del_by_context(global ? server->global_list->clients :
444 server->local_list->clients, client);
445 silc_idcache_add(global ? server->global_list->clients :
446 server->local_list->clients, nick, client->id,
450 /* If client is global and is not on any channel then add that we'll
451 expire the entry after a while. */
453 silc_idlist_find_client_by_id(server->global_list, client->id,
455 if (!silc_hash_table_count(client->channels))
456 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
461 silc_free(client_id);
466 /* Received reply for WHOWAS command. Cache the client information only for
467 a short period of time. */
469 SILC_SERVER_CMD_REPLY_FUNC(whowas)
471 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
472 SilcStatus status, error;
474 COMMAND_CHECK_STATUS;
476 if (!silc_server_command_reply_whowas_save(cmd))
479 /* Pending callbacks are not executed if this was an list entry */
480 if (status != SILC_STATUS_OK &&
481 status != SILC_STATUS_LIST_END) {
482 silc_server_command_reply_free(cmd);
487 silc_server_command_process_error(cmd, error);
488 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
489 silc_server_command_reply_free(cmd);
493 silc_server_command_process_error(cmd, error);
494 silc_server_command_reply_free(cmd);
497 /* Caches the received IDENTIFY information. */
500 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
502 SilcServer server = cmd->server;
503 SilcUInt32 len, id_len;
504 unsigned char *id_data;
506 SilcClientID *client_id = NULL;
507 SilcServerID *server_id = NULL;
508 SilcChannelID *channel_id = NULL;
509 SilcClientEntry client;
510 SilcServerEntry server_entry;
511 SilcChannelEntry channel;
514 SilcIDPayload idp = NULL;
518 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
521 idp = silc_id_payload_parse(id_data, id_len);
525 name = silc_argument_get_arg_type(cmd->args, 3, &len);
526 info = silc_argument_get_arg_type(cmd->args, 4, &len);
528 id_type = silc_id_payload_get_type(idp);
532 client_id = silc_id_payload_get_id(idp);
536 SILC_LOG_DEBUG(("Received client information"));
538 client = silc_idlist_find_client_by_id(server->local_list,
539 client_id, FALSE, NULL);
541 client = silc_idlist_find_client_by_id(server->global_list, client_id,
546 /* If router did not find such Client ID in its lists then this must
547 be bogus client or some router in the net is buggy. */
548 if (server->server_type != SILC_SERVER)
553 silc_parse_userfqdn(name, &nick, NULL);
555 /* We don't have that client anywhere, add it. The client is added
556 to global list since server didn't have it in the lists so it must be
558 client = silc_idlist_add_client(server->global_list, nick,
559 info ? strdup(info) : NULL, NULL,
560 client_id, cmd->sock->user_data,
561 NULL, time(NULL) + 300);
563 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
566 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
567 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
568 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
570 /* We have the client already, update the data */
572 SILC_LOG_DEBUG(("Updating client data"));
576 silc_parse_userfqdn(name, &nick, NULL);
578 /* Remove the old cache entry */
579 silc_idcache_del_by_context(global ? server->global_list->clients :
580 server->local_list->clients, client);
582 silc_free(client->nickname);
583 client->nickname = nick;
587 silc_free(client->username);
588 client->username = strdup(info);
591 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
592 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
595 /* Add new cache entry */
596 silc_idcache_add(global ? server->global_list->clients :
597 server->local_list->clients, nick, client->id,
598 client, expire, NULL);
601 /* If client is global and is not on any channel then add that we'll
602 expire the entry after a while. */
603 if (global && server->server_type == SILC_SERVER) {
604 SilcIDCacheEntry cache = NULL;
605 silc_idlist_find_client_by_id(server->global_list, client->id,
607 if (!silc_hash_table_count(client->channels))
608 cache->expire = time(NULL) + 300;
613 silc_free(client_id);
622 server_id = silc_id_payload_get_id(idp);
626 SILC_LOG_DEBUG(("Received server information"));
628 server_entry = silc_idlist_find_server_by_id(server->local_list,
629 server_id, FALSE, NULL);
631 server_entry = silc_idlist_find_server_by_id(server->global_list,
632 server_id, FALSE, NULL);
634 /* If router did not find such Server ID in its lists then this must
635 be bogus server or some router in the net is buggy. */
636 if (server->server_type != SILC_SERVER)
639 /* We don't have that server anywhere, add it. */
640 server_entry = silc_idlist_add_server(server->global_list,
642 server_id, server->router,
643 SILC_PRIMARY_ROUTE(server));
645 silc_free(server_id);
648 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
649 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
650 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
654 silc_free(server_id);
657 case SILC_ID_CHANNEL:
661 channel_id = silc_id_payload_get_id(idp);
665 SILC_LOG_DEBUG(("Received channel information"));
667 channel = silc_idlist_find_channel_by_name(server->local_list,
670 channel = silc_idlist_find_channel_by_name(server->global_list,
673 /* If router did not find such Channel ID in its lists then this must
674 be bogus channel or some router in the net is buggy. */
675 if (server->server_type != SILC_SERVER)
678 /* We don't have that channel anywhere, add it. */
679 channel = silc_idlist_add_channel(server->global_list, strdup(name),
680 SILC_CHANNEL_MODE_NONE, channel_id,
681 server->router, NULL, NULL, 0);
683 silc_free(channel_id);
689 silc_free(channel_id);
693 silc_id_payload_free(idp);
697 silc_id_payload_free(idp);
701 /* Received reply for forwarded IDENTIFY command. We have received the
702 requested identify information now and we will cache it. After this we
703 will call the pending command so that the requestee gets the information
706 SILC_SERVER_CMD_REPLY_FUNC(identify)
708 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
709 SilcStatus status, error;
711 COMMAND_CHECK_STATUS;
713 if (!silc_server_command_reply_identify_save(cmd))
716 /* Pending callbacks are not executed if this was an list entry */
717 if (status != SILC_STATUS_OK &&
718 status != SILC_STATUS_LIST_END) {
719 silc_server_command_reply_free(cmd);
724 silc_server_command_process_error(cmd, error);
725 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
726 silc_server_command_reply_free(cmd);
730 silc_server_command_process_error(cmd, error);
731 silc_server_command_reply_free(cmd);
734 /* Received reply fro INFO command. Cache the server and its information */
736 SILC_SERVER_CMD_REPLY_FUNC(info)
738 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
739 SilcServer server = cmd->server;
740 SilcStatus status, error;
741 SilcServerEntry entry;
742 SilcServerID *server_id;
744 unsigned char *tmp, *name;
746 COMMAND_CHECK_STATUS;
749 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
752 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
757 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
761 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
764 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
767 /* Add the server to global list */
768 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
769 entry = silc_idlist_add_server(server->global_list, name, 0,
770 server_id, cmd->sock->user_data,
773 silc_free(server_id);
776 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
780 /* Get the info string */
781 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
785 entry->server_info = tmp ? strdup(tmp) : NULL;
788 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
790 silc_server_command_reply_free(cmd);
793 /* Received reply fro MOTD command. */
795 SILC_SERVER_CMD_REPLY_FUNC(motd)
797 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
798 SilcServer server = cmd->server;
799 SilcStatus status, error;
800 SilcServerEntry entry = NULL;
801 SilcServerID *server_id;
805 COMMAND_CHECK_STATUS;
808 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
811 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
815 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
818 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
825 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
832 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
834 silc_server_command_reply_free(cmd);
840 /* Received reply for forwarded JOIN command. Router has created or joined
841 the client to the channel. We save some channel information locally
844 SILC_SERVER_CMD_REPLY_FUNC(join)
846 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
847 SilcServer server = cmd->server;
848 SilcIDCacheEntry cache = NULL;
849 SilcStatus status, error;
851 SilcClientID *client_id = NULL;
852 SilcChannelEntry entry;
853 SilcHmac hmac = NULL;
854 SilcUInt32 id_len, len, list_count;
855 unsigned char *id_string;
856 char *channel_name, *tmp;
857 SilcUInt32 mode, created;
858 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
859 SilcPublicKey founder_key = NULL;
861 COMMAND_CHECK_STATUS;
863 /* Get channel name */
864 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
869 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
874 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
877 client_id = silc_id_payload_parse_id(tmp, len, NULL);
882 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
885 SILC_GET32_MSB(mode, tmp);
887 /* Get created boolean value */
888 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
891 SILC_GET32_MSB(created, tmp);
892 if (created != 0 && created != 1)
895 /* Get channel key */
896 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
898 keyp = silc_buffer_alloc(len);
899 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
900 silc_buffer_put(keyp, tmp, len);
903 /* Parse the Channel ID */
904 id = silc_id_payload_parse_id(id_string, id_len, NULL);
909 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
911 if (!silc_hmac_alloc(tmp, NULL, &hmac))
915 /* Get the list count */
916 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
919 SILC_GET32_MSB(list_count, tmp);
921 /* Get Client ID list */
922 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
926 client_id_list = silc_buffer_alloc(len);
927 silc_buffer_pull_tail(client_id_list, len);
928 silc_buffer_put(client_id_list, tmp, len);
930 /* Get client mode list */
931 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
935 client_mode_list = silc_buffer_alloc(len);
936 silc_buffer_pull_tail(client_mode_list, len);
937 silc_buffer_put(client_mode_list, tmp, len);
939 /* Get founder key */
940 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
942 silc_pkcs_public_key_decode(tmp, len, &founder_key);
944 /* See whether we already have the channel. */
945 entry = silc_idlist_find_channel_by_name(server->local_list,
946 channel_name, &cache);
948 /* Add new channel */
950 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
951 (created == 0 ? "existing" : "created"), channel_name,
952 silc_id_render(id, SILC_ID_CHANNEL)));
954 /* If the channel is found from global list we must move it to the
956 entry = silc_idlist_find_channel_by_name(server->global_list,
957 channel_name, &cache);
959 silc_idlist_del_channel(server->global_list, entry);
961 /* Add the channel to our local list. */
962 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
963 SILC_CHANNEL_MODE_NONE, id,
964 server->router, NULL, hmac, 0);
970 server->stat.my_channels++;
971 server->stat.channels++;
973 /* The entry exists. */
975 /* If ID has changed, then update it to the cache too. */
976 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
977 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
979 entry->disabled = FALSE;
981 /* Remove the founder auth data if the mode is not set but we have
983 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
984 silc_pkcs_public_key_free(entry->founder_key);
985 entry->founder_key = NULL;
990 if (entry->founder_key)
991 silc_pkcs_public_key_free(entry->founder_key);
992 entry->founder_key = founder_key;
996 if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
997 silc_free(entry->hmac_name);
998 entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1001 /* Get the ban list */
1002 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1004 silc_free(entry->ban_list);
1005 entry->ban_list = silc_memdup(tmp, len);
1008 /* Get the invite list */
1009 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1011 silc_free(entry->invite_list);
1012 entry->invite_list = silc_memdup(tmp, len);
1016 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1018 silc_free(entry->topic);
1019 entry->topic = strdup(tmp);
1022 /* If channel was not created we know there is global users on the
1024 entry->global_users = (created == 0 ? TRUE : FALSE);
1026 /* If channel was just created the mask must be zero */
1027 if (!entry->global_users && mode) {
1028 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
1029 "new channel, forcing it to zero", cmd->sock->hostname));
1033 /* Save channel mode */
1036 /* Save channel key */
1038 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1039 silc_server_save_channel_key(server, keyp, entry);
1040 silc_buffer_free(keyp);
1043 /* Save the users to the channel */
1044 silc_server_save_users_on_channel(server, cmd->sock, entry,
1045 client_id, client_id_list,
1046 client_mode_list, list_count);
1047 entry->users_resolved = TRUE;
1050 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1053 silc_hmac_free(hmac);
1054 silc_free(client_id);
1055 silc_server_command_reply_free(cmd);
1057 silc_pkcs_public_key_free(founder_key);
1059 silc_buffer_free(client_id_list);
1060 if (client_mode_list)
1061 silc_buffer_free(client_mode_list);
1064 /* Received reply to STATS command. */
1066 SILC_SERVER_CMD_REPLY_FUNC(stats)
1068 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1069 SilcServer server = cmd->server;
1070 SilcStatus status, error;
1073 SilcBufferStruct buf;
1075 COMMAND_CHECK_STATUS;
1077 /* Get statistics structure */
1078 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1079 if (server->server_type != SILC_ROUTER && tmp) {
1080 silc_buffer_set(&buf, tmp, tmp_len);
1081 silc_buffer_unformat(&buf,
1082 SILC_STR_UI_INT(NULL),
1083 SILC_STR_UI_INT(NULL),
1084 SILC_STR_UI_INT(NULL),
1085 SILC_STR_UI_INT(NULL),
1086 SILC_STR_UI_INT(NULL),
1087 SILC_STR_UI_INT(NULL),
1088 SILC_STR_UI_INT(&server->stat.cell_clients),
1089 SILC_STR_UI_INT(&server->stat.cell_channels),
1090 SILC_STR_UI_INT(&server->stat.cell_servers),
1091 SILC_STR_UI_INT(&server->stat.clients),
1092 SILC_STR_UI_INT(&server->stat.channels),
1093 SILC_STR_UI_INT(&server->stat.servers),
1094 SILC_STR_UI_INT(&server->stat.routers),
1095 SILC_STR_UI_INT(&server->stat.server_ops),
1096 SILC_STR_UI_INT(&server->stat.router_ops),
1101 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1103 silc_server_command_reply_free(cmd);
1106 SILC_SERVER_CMD_REPLY_FUNC(users)
1108 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1109 SilcServer server = cmd->server;
1110 SilcStatus status, error;
1111 SilcChannelEntry channel;
1112 SilcChannelID *channel_id = NULL;
1113 SilcBuffer client_id_list;
1114 SilcBuffer client_mode_list;
1117 SilcUInt32 list_count;
1119 COMMAND_CHECK_STATUS;
1121 /* Get channel ID */
1122 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1125 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1129 /* Get channel entry */
1130 channel = silc_idlist_find_channel_by_id(server->local_list,
1133 channel = silc_idlist_find_channel_by_id(server->global_list,
1138 if (server->server_type != SILC_SERVER)
1141 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1142 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1143 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1144 1, 5, idp->data, idp->len);
1145 silc_buffer_free(idp);
1147 /* Register pending command callback. After we've received the channel
1148 information we will reprocess this command reply by re-calling this
1149 USERS command reply callback. */
1150 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1152 silc_server_command_reply_users, cmd);
1157 /* Get the list count */
1158 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1161 SILC_GET32_MSB(list_count, tmp);
1163 /* Get Client ID list */
1164 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1168 client_id_list = silc_buffer_alloc(tmp_len);
1169 silc_buffer_pull_tail(client_id_list, tmp_len);
1170 silc_buffer_put(client_id_list, tmp, tmp_len);
1172 /* Get client mode list */
1173 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1177 client_mode_list = silc_buffer_alloc(tmp_len);
1178 silc_buffer_pull_tail(client_mode_list, tmp_len);
1179 silc_buffer_put(client_mode_list, tmp, tmp_len);
1181 /* Save the users to the channel */
1182 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1183 client_id_list, client_mode_list,
1186 channel->global_users = silc_server_channel_has_global(channel);
1187 channel->users_resolved = TRUE;
1189 silc_buffer_free(client_id_list);
1190 silc_buffer_free(client_mode_list);
1193 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1194 silc_free(channel_id);
1196 silc_server_command_reply_free(cmd);
1199 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1201 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1202 SilcServer server = cmd->server;
1203 SilcStatus status, error;
1204 SilcClientEntry client = NULL;
1205 SilcServerEntry server_entry = NULL;
1206 SilcClientID *client_id = NULL;
1207 SilcServerID *server_id = NULL;
1209 unsigned char *tmp, *pk;
1212 SilcIDPayload idp = NULL;
1214 SilcPublicKey public_key = NULL;
1216 COMMAND_CHECK_STATUS;
1218 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1221 idp = silc_id_payload_parse(tmp, len);
1225 /* Get the public key payload */
1226 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1230 /* Decode the public key */
1232 SILC_GET16_MSB(pk_len, tmp);
1233 SILC_GET16_MSB(type, tmp + 2);
1236 if (type != SILC_SKE_PK_TYPE_SILC)
1239 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1242 id_type = silc_id_payload_get_type(idp);
1243 if (id_type == SILC_ID_CLIENT) {
1244 client_id = silc_id_payload_get_id(idp);
1246 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1249 client = silc_idlist_find_client_by_id(server->global_list,
1250 client_id, TRUE, NULL);
1255 client->data.public_key = public_key;
1257 } else if (id_type == SILC_ID_SERVER) {
1258 server_id = silc_id_payload_get_id(idp);
1260 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1262 if (!server_entry) {
1263 server_entry = silc_idlist_find_server_by_id(server->global_list,
1264 server_id, TRUE, NULL);
1269 server_entry->data.public_key = public_key;
1276 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1278 silc_id_payload_free(idp);
1279 silc_free(client_id);
1280 silc_free(server_id);
1282 silc_pkcs_public_key_free(public_key);
1284 silc_server_command_reply_free(cmd);
1287 SILC_SERVER_CMD_REPLY_FUNC(list)
1289 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1290 SilcServer server = cmd->server;
1291 SilcStatus status, error;
1292 SilcChannelID *channel_id = NULL;
1293 SilcChannelEntry channel;
1294 SilcIDCacheEntry cache;
1296 unsigned char *tmp, *name, *topic;
1297 SilcUInt32 usercount = 0;
1298 bool global_list = FALSE;
1300 COMMAND_CHECK_STATUS;
1302 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1303 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1307 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1308 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1309 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1311 SILC_GET32_MSB(usercount, tmp);
1313 /* Add the channel entry if we do not have it already */
1314 channel = silc_idlist_find_channel_by_name(server->local_list,
1317 channel = silc_idlist_find_channel_by_name(server->global_list,
1322 /* If router did not find such channel in its lists then this must
1323 be bogus channel or some router in the net is buggy. */
1324 if (server->server_type != SILC_SERVER)
1327 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1328 SILC_CHANNEL_MODE_NONE, channel_id,
1329 server->router, NULL, NULL,
1335 /* Found, update expiry */
1336 if (global_list && server->server_type == SILC_SERVER)
1337 cache->expire = time(NULL) + 60;
1340 channel->user_count = usercount;
1343 silc_free(channel->topic);
1344 channel->topic = strdup(topic);
1347 /* Pending callbacks are not executed if this was an list entry */
1348 if (status != SILC_STATUS_OK &&
1349 status != SILC_STATUS_LIST_END) {
1350 silc_server_command_reply_free(cmd);
1354 /* Now purge all old entries from the global list, otherwise we'll might
1355 have non-existent entries for long periods of time in the cache. */
1356 silc_idcache_purge(server->global_list->channels);
1359 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1360 silc_free(channel_id);
1362 silc_server_command_reply_free(cmd);
1365 SILC_SERVER_CMD_REPLY_FUNC(watch)
1367 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1368 SilcStatus status, error;
1370 COMMAND_CHECK_STATUS;
1373 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1375 silc_server_command_reply_free(cmd);