5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2003 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "serverincludes.h"
22 #include "server_internal.h"
23 #include "command_reply.h"
25 /* All functions that call the COMMAND_CHECK_STATUS macros must have
26 out: and err: goto labels. */
28 #define COMMAND_CHECK_STATUS \
30 SILC_LOG_DEBUG(("Start")); \
31 if (!silc_command_get_status(cmd->payload, &status, &error)) { \
32 if (SILC_STATUS_IS_ERROR(status)) \
34 if (status == SILC_STATUS_LIST_END) \
40 /* Server command reply list. Not all commands have reply function as
41 they are never sent by server. More maybe added later if need appears. */
42 SilcServerCommandReply silc_command_reply_list[] =
44 SILC_SERVER_CMD_REPLY(whois, WHOIS),
45 SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
46 SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
47 SILC_SERVER_CMD_REPLY(info, INFO),
48 SILC_SERVER_CMD_REPLY(motd, MOTD),
49 SILC_SERVER_CMD_REPLY(join, JOIN),
50 SILC_SERVER_CMD_REPLY(stats, STATS),
51 SILC_SERVER_CMD_REPLY(users, USERS),
52 SILC_SERVER_CMD_REPLY(getkey, GETKEY),
53 SILC_SERVER_CMD_REPLY(list, LIST),
54 SILC_SERVER_CMD_REPLY(watch, WATCH),
55 SILC_SERVER_CMD_REPLY(ping, PING),
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_payload_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);
1003 if (tmp && len > 2) {
1004 SilcArgumentPayload iargs;
1006 SILC_GET16_MSB(iargc, tmp);
1007 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1009 /* Delete old ban list */
1010 if (entry->ban_list)
1011 silc_hash_table_free(entry->ban_list);
1013 silc_hash_table_alloc(0, silc_hash_ptr,
1015 silc_server_inviteban_destruct, entry, TRUE);
1017 /* Add new ban list */
1018 silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1019 silc_argument_payload_free(iargs);
1023 /* Get the invite list */
1024 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1025 if (tmp && len > 2) {
1026 SilcArgumentPayload iargs;
1028 SILC_GET16_MSB(iargc, tmp);
1029 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1031 /* Delete old invite list */
1032 if (entry->invite_list)
1033 silc_hash_table_free(entry->invite_list);
1034 entry->invite_list =
1035 silc_hash_table_alloc(0, silc_hash_ptr,
1037 silc_server_inviteban_destruct, entry, TRUE);
1039 /* Add new invite list */
1040 silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1041 silc_argument_payload_free(iargs);
1046 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1048 silc_free(entry->topic);
1049 entry->topic = strdup(tmp);
1052 /* Get channel public key list */
1053 tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1054 if (tmp && server->server_type == SILC_SERVER)
1055 silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1057 /* If channel was not created we know there is global users on the
1059 entry->global_users = (created == 0 ? TRUE : FALSE);
1061 /* If channel was just created the mask must be zero */
1062 if (!entry->global_users && mode) {
1063 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
1064 "new channel, forcing it to zero", cmd->sock->hostname));
1068 /* Save channel mode */
1071 /* Save channel key */
1073 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1074 silc_server_save_channel_key(server, keyp, entry);
1075 silc_buffer_free(keyp);
1078 /* Save the users to the channel */
1079 silc_server_save_users_on_channel(server, cmd->sock, entry,
1080 client_id, client_id_list,
1081 client_mode_list, list_count);
1082 entry->users_resolved = TRUE;
1085 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1088 silc_hmac_free(hmac);
1089 silc_free(client_id);
1090 silc_server_command_reply_free(cmd);
1092 silc_pkcs_public_key_free(founder_key);
1094 silc_buffer_free(client_id_list);
1095 if (client_mode_list)
1096 silc_buffer_free(client_mode_list);
1099 /* Received reply to STATS command. */
1101 SILC_SERVER_CMD_REPLY_FUNC(stats)
1103 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1104 SilcServer server = cmd->server;
1105 SilcStatus status, error;
1108 SilcBufferStruct buf;
1110 COMMAND_CHECK_STATUS;
1112 /* Get statistics structure */
1113 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1114 if (server->server_type != SILC_ROUTER && tmp) {
1115 silc_buffer_set(&buf, tmp, tmp_len);
1116 silc_buffer_unformat(&buf,
1117 SILC_STR_UI_INT(NULL),
1118 SILC_STR_UI_INT(NULL),
1119 SILC_STR_UI_INT(NULL),
1120 SILC_STR_UI_INT(NULL),
1121 SILC_STR_UI_INT(NULL),
1122 SILC_STR_UI_INT(NULL),
1123 SILC_STR_UI_INT(&server->stat.cell_clients),
1124 SILC_STR_UI_INT(&server->stat.cell_channels),
1125 SILC_STR_UI_INT(&server->stat.cell_servers),
1126 SILC_STR_UI_INT(&server->stat.clients),
1127 SILC_STR_UI_INT(&server->stat.channels),
1128 SILC_STR_UI_INT(&server->stat.servers),
1129 SILC_STR_UI_INT(&server->stat.routers),
1130 SILC_STR_UI_INT(&server->stat.server_ops),
1131 SILC_STR_UI_INT(&server->stat.router_ops),
1136 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1138 silc_server_command_reply_free(cmd);
1141 SILC_SERVER_CMD_REPLY_FUNC(users)
1143 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1144 SilcServer server = cmd->server;
1145 SilcStatus status, error;
1146 SilcChannelEntry channel;
1147 SilcChannelID *channel_id = NULL;
1148 SilcBuffer client_id_list;
1149 SilcBuffer client_mode_list;
1152 SilcUInt32 list_count;
1154 COMMAND_CHECK_STATUS;
1156 /* Get channel ID */
1157 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1160 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1164 /* Get channel entry */
1165 channel = silc_idlist_find_channel_by_id(server->local_list,
1168 channel = silc_idlist_find_channel_by_id(server->global_list,
1173 if (server->server_type != SILC_SERVER)
1176 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1177 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1178 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1179 1, 5, idp->data, idp->len);
1180 silc_buffer_free(idp);
1182 /* Register pending command callback. After we've received the channel
1183 information we will reprocess this command reply by re-calling this
1184 USERS command reply callback. */
1185 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1187 silc_server_command_reply_users, cmd);
1192 /* Get the list count */
1193 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1196 SILC_GET32_MSB(list_count, tmp);
1198 /* Get Client ID list */
1199 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1203 client_id_list = silc_buffer_alloc(tmp_len);
1204 silc_buffer_pull_tail(client_id_list, tmp_len);
1205 silc_buffer_put(client_id_list, tmp, tmp_len);
1207 /* Get client mode list */
1208 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1212 client_mode_list = silc_buffer_alloc(tmp_len);
1213 silc_buffer_pull_tail(client_mode_list, tmp_len);
1214 silc_buffer_put(client_mode_list, tmp, tmp_len);
1216 /* Save the users to the channel */
1217 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1218 client_id_list, client_mode_list,
1221 channel->global_users = silc_server_channel_has_global(channel);
1222 channel->users_resolved = TRUE;
1224 silc_buffer_free(client_id_list);
1225 silc_buffer_free(client_mode_list);
1228 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1229 silc_free(channel_id);
1231 silc_server_command_reply_free(cmd);
1234 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1236 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1237 SilcServer server = cmd->server;
1238 SilcStatus status, error;
1239 SilcClientEntry client = NULL;
1240 SilcServerEntry server_entry = NULL;
1241 SilcClientID *client_id = NULL;
1242 SilcServerID *server_id = NULL;
1245 SilcIDPayload idp = NULL;
1247 SilcPublicKey public_key = NULL;
1249 COMMAND_CHECK_STATUS;
1251 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1254 idp = silc_id_payload_parse(tmp, len);
1258 /* Get the public key payload */
1259 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1263 /* Decode the public key payload */
1264 if (!silc_pkcs_public_key_payload_decode(tmp, len, &public_key))
1267 id_type = silc_id_payload_get_type(idp);
1268 if (id_type == SILC_ID_CLIENT) {
1269 client_id = silc_id_payload_get_id(idp);
1271 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1274 client = silc_idlist_find_client_by_id(server->global_list,
1275 client_id, TRUE, NULL);
1280 client->data.public_key = public_key;
1282 } else if (id_type == SILC_ID_SERVER) {
1283 server_id = silc_id_payload_get_id(idp);
1285 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1287 if (!server_entry) {
1288 server_entry = silc_idlist_find_server_by_id(server->global_list,
1289 server_id, TRUE, NULL);
1294 server_entry->data.public_key = public_key;
1301 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1303 silc_id_payload_free(idp);
1304 silc_free(client_id);
1305 silc_free(server_id);
1307 silc_pkcs_public_key_free(public_key);
1309 silc_server_command_reply_free(cmd);
1312 SILC_SERVER_CMD_REPLY_FUNC(list)
1314 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1315 SilcServer server = cmd->server;
1316 SilcStatus status, error;
1317 SilcChannelID *channel_id = NULL;
1318 SilcChannelEntry channel;
1319 SilcIDCacheEntry cache;
1321 unsigned char *tmp, *name, *topic;
1322 SilcUInt32 usercount = 0;
1323 bool global_list = FALSE;
1325 COMMAND_CHECK_STATUS;
1327 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1328 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1332 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1333 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1334 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1336 SILC_GET32_MSB(usercount, tmp);
1338 /* Add the channel entry if we do not have it already */
1339 channel = silc_idlist_find_channel_by_name(server->local_list,
1342 channel = silc_idlist_find_channel_by_name(server->global_list,
1347 /* If router did not find such channel in its lists then this must
1348 be bogus channel or some router in the net is buggy. */
1349 if (server->server_type != SILC_SERVER)
1352 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1353 SILC_CHANNEL_MODE_NONE, channel_id,
1354 server->router, NULL, NULL,
1360 /* Found, update expiry */
1361 if (global_list && server->server_type == SILC_SERVER)
1362 cache->expire = time(NULL) + 60;
1365 channel->user_count = usercount;
1368 silc_free(channel->topic);
1369 channel->topic = strdup(topic);
1372 /* Pending callbacks are not executed if this was an list entry */
1373 if (status != SILC_STATUS_OK &&
1374 status != SILC_STATUS_LIST_END) {
1375 silc_server_command_reply_free(cmd);
1379 /* Now purge all old entries from the global list, otherwise we'll might
1380 have non-existent entries for long periods of time in the cache. */
1381 silc_idcache_purge(server->global_list->channels);
1384 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1385 silc_free(channel_id);
1387 silc_server_command_reply_free(cmd);
1390 SILC_SERVER_CMD_REPLY_FUNC(watch)
1392 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1393 SilcStatus status, error;
1395 COMMAND_CHECK_STATUS;
1398 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1400 silc_server_command_reply_free(cmd);
1403 SILC_SERVER_CMD_REPLY_FUNC(ping)
1405 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1406 SilcStatus status, error;
1408 COMMAND_CHECK_STATUS;
1411 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1413 silc_server_command_reply_free(cmd);