5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005, 2007 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 SilcPacketStream sock,
66 SilcIDListData idata = silc_packet_get_context(sock);
67 SilcServerCommandReply *cmd;
68 SilcServerCommandReplyContext ctx;
69 SilcCommandPayload payload;
72 SILC_LOG_DEBUG(("Start"));
74 /* Get command reply payload from packet */
75 payload = silc_command_payload_parse(buffer->data, silc_buffer_len(buffer));
77 /* Silently ignore bad reply packet */
78 SILC_LOG_DEBUG(("Bad command reply packet"));
82 /* Allocate command reply context. This must be free'd by the
83 command reply routine receiving it. */
84 ctx = silc_calloc(1, sizeof(*ctx));
87 ctx->payload = payload;
88 ctx->args = silc_command_get_args(ctx->payload);
89 ctx->ident = silc_command_get_ident(ctx->payload);
90 command = silc_command_get(ctx->payload);
91 silc_packet_stream_ref(sock);
93 /* Client is not allowed to send reply to all commands */
94 if (idata->conn_type == SILC_CONN_CLIENT &&
95 command != SILC_COMMAND_WHOIS) {
96 silc_server_command_reply_free(ctx);
100 /* Check for pending commands and mark to be exeucted */
102 silc_server_command_pending_check(server, command,
103 ctx->ident, &ctx->callbacks_count);
105 /* Execute command reply */
106 for (cmd = silc_command_reply_list; cmd->cb; cmd++)
107 if (cmd->cmd == command)
110 if (cmd == NULL || !cmd->cb) {
111 silc_server_command_reply_free(ctx);
118 /* Free command reply context and its internals. */
120 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
123 silc_command_payload_free(cmd->payload);
125 silc_packet_stream_unref(cmd->sock);
126 silc_free(cmd->callbacks);
132 silc_server_command_process_error(SilcServerCommandReplyContext cmd,
135 SilcServer server = cmd->server;
136 SilcIDListData idata = silc_packet_get_context(cmd->sock);
138 /* If we received notify for invalid ID we'll remove the ID if we
140 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
141 idata->conn_type == SILC_CONN_ROUTER) {
142 SilcClientEntry client;
144 if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id,
146 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
147 "the entry from cache"));
148 client = silc_idlist_find_client_by_id(server->global_list,
149 SILC_ID_GET_ID(id), FALSE, NULL);
153 if (client->data.public_key)
154 silc_hash_table_del_by_context(server->pk_hash,
155 client->data.public_key,
158 silc_server_remove_from_channels(server, NULL, client, TRUE,
160 silc_idlist_del_data(client);
161 silc_idlist_del_client(server->global_list, client);
166 /* Caches the received WHOIS information. */
169 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
171 SilcServer server = cmd->server;
172 unsigned char *id_data, *umodes;
173 char *nickname, *username, *realname, *tmp;
174 unsigned char *fingerprint;
176 SilcClientEntry client;
178 char nick[128 + 1], servername[256 + 1], uname[128 + 1];
179 SilcUInt32 mode = 0, len, len2, id_len, flen;
180 const char *hostname, *ip;
182 silc_socket_stream_get_info(cmd->sock, NULL, &hostname, &ip, NULL);
184 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
185 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
186 username = silc_argument_get_arg_type(cmd->args, 4, &len);
187 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
188 if (!id_data || !nickname || !username || !realname)
191 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
193 SILC_GET32_MSB(mode, tmp);
195 if (!silc_id_payload_parse_id(id_data, id_len, &id))
198 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
200 /* Check if we have this client cached already. */
202 client = silc_idlist_find_client_by_id(server->local_list,
206 client = silc_idlist_find_client_by_id(server->global_list,
213 /* If router did not find such Client ID in its lists then this must
214 be bogus client or some router in the net is buggy. */
215 if (server->server_type != SILC_SERVER)
218 /* Take hostname out of nick string if it includes it. */
219 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
222 /* We don't have that client anywhere, add it. The client is added
223 to global list since server didn't have it in the lists so it must be
224 global. This will check for valid nickname and username strings. */
225 client = silc_idlist_add_client(server->global_list,
226 strdup(nick), username,
228 silc_id_dup(SILC_ID_GET_ID(id),
230 silc_packet_get_context(cmd->sock),
233 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
237 client->data.status |=
238 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
239 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
241 client->servername = servername[0] ? strdup(servername) : NULL;
243 /* We have the client already, update the data */
245 SILC_LOG_DEBUG(("Updating client data"));
248 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
250 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
253 SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOIS reply "
255 hostname ? hostname : "", nick));
260 silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
261 if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128)) {
262 SILC_LOG_ERROR(("Malformed username '%s' received in WHOIS reply "
264 hostname ? hostname : "", tmp));
268 /* Remove the old cache entry */
269 silc_idcache_del_by_context(global ? server->global_list->clients :
270 server->local_list->clients, client, NULL);
272 silc_free(client->nickname);
273 silc_free(client->username);
274 silc_free(client->userinfo);
275 silc_free(client->servername);
277 client->nickname = strdup(nick);
278 client->username = strdup(username);
279 client->userinfo = strdup(realname);
280 client->servername = servername[0] ? strdup(servername) : NULL;
282 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
283 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
285 /* Create new cache entry */
286 silc_idcache_add(global ? server->global_list->clients :
287 server->local_list->clients, nickname, client->id,
291 /* Save channel list if it was sent to us */
292 if (server->server_type == SILC_SERVER) {
293 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
294 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
296 SilcBufferStruct channels_buf, umodes_buf;
297 silc_buffer_set(&channels_buf, tmp, len);
298 silc_buffer_set(&umodes_buf, umodes, len2);
299 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
302 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
306 if (fingerprint && flen == sizeof(client->data.fingerprint))
307 memcpy(client->data.fingerprint, fingerprint, flen);
309 /* Take Requested Attributes if set. */
310 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
312 silc_free(client->attrs);
313 client->attrs = silc_memdup(tmp, len);
314 client->attrs_len = len;
316 /* Try to take public key from attributes if present and we don't have
317 the key already. Do this only on normal server. Routers do GETKEY
318 for all clients anyway. */
319 if (server->server_type != SILC_ROUTER && !client->data.public_key) {
320 SilcAttributePayload attr;
321 SilcAttributeObjPk pk;
322 unsigned char f[SILC_HASH_MAXLEN];
323 SilcDList attrs = silc_attribute_payload_parse(tmp, len);
325 SILC_LOG_DEBUG(("Take client public key from attributes"));
328 silc_dlist_start(attrs);
329 while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
330 if (silc_attribute_get_attribute(attr) ==
331 SILC_ATTRIBUTE_USER_PUBLIC_KEY) {
333 if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
336 /* Take only SILC public keys */
337 if (strcmp(pk.type, "silc-rsa")) {
343 /* Verify that the server provided fingerprint matches the key */
344 silc_hash_make(server->sha1hash, pk.data, pk.data_len, f);
345 if (memcmp(f, client->data.fingerprint, sizeof(f))) {
351 /* Save the public key. */
352 if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC,
353 pk.data, pk.data_len,
354 &client->data.public_key)) {
360 SILC_LOG_DEBUG(("Saved client public key from attributes"));
362 /* Add to public key hash table */
363 if (!silc_hash_table_find_by_context(server->pk_hash,
364 client->data.public_key,
366 silc_hash_table_add(server->pk_hash,
367 client->data.public_key, client);
375 silc_attribute_payload_list_free(attrs);
383 /* Handle requested attributes reply in WHOIS from client */
386 silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd)
390 SilcClientEntry client = silc_packet_get_context(cmd->sock);
392 /* Take Requested Attributes if set. */
393 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
395 silc_free(client->attrs);
396 client->attrs = silc_memdup(tmp, len);
397 client->attrs_len = len;
400 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
405 /* Reiceved reply for WHOIS command. We sent the whois request to our
406 primary router, if we are normal server, and thus has now received reply
407 to the command. We will figure out what client originally sent us the
408 command and will send the reply to it. If we are router we will figure
409 out who server sent us the command and send reply to that one. */
411 SILC_SERVER_CMD_REPLY_FUNC(whois)
413 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
414 SilcIDListData idata = silc_packet_get_context(cmd->sock);
415 SilcStatus status, error;
417 COMMAND_CHECK_STATUS;
419 if (idata->conn_type != SILC_CONN_CLIENT) {
420 if (!silc_server_command_reply_whois_save(cmd))
423 if (!silc_server_command_reply_whois_save_client(cmd))
427 /* Pending callbacks are not executed if this was an list entry */
428 if (status != SILC_STATUS_OK &&
429 status != SILC_STATUS_LIST_END) {
430 silc_server_command_reply_free(cmd);
435 silc_server_command_process_error(cmd, error);
436 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
437 silc_server_command_reply_free(cmd);
441 silc_server_command_process_error(cmd, error);
442 silc_server_command_reply_free(cmd);
445 /* Caches the received WHOWAS information for a short period of time. */
448 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
450 SilcServer server = cmd->server;
451 SilcUInt32 len, id_len;
452 unsigned char *id_data;
453 char *nickname, *username, *realname;
455 SilcClientEntry client;
456 SilcIDCacheEntry cache = NULL;
457 char nick[128 + 1], servername[256 + 1], uname[128 + 1];
459 const char *hostname, *ip;
461 silc_socket_stream_get_info(cmd->sock, NULL, &hostname, &ip, NULL);
463 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
464 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
465 username = silc_argument_get_arg_type(cmd->args, 4, &len);
466 if (!id_data || !nickname || !username)
469 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
471 if (!silc_id_payload_parse_id(id_data, id_len, &id))
474 /* Check if we have this client cached already. */
476 client = silc_idlist_find_client_by_id(server->local_list,
480 client = silc_idlist_find_client_by_id(server->global_list,
487 /* If router did not find such Client ID in its lists then this must
488 be bogus client or some router in the net is buggy. */
489 if (server->server_type != SILC_SERVER)
492 /* Take hostname out of nick string if it includes it. */
493 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
496 /* We don't have that client anywhere, add it. The client is added
497 to global list since server didn't have it in the lists so it must be
499 client = silc_idlist_add_client(server->global_list,
500 strdup(nick), username,
502 silc_id_dup(SILC_ID_GET_ID(id),
504 silc_packet_get_context(cmd->sock), NULL);
506 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
510 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
511 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
512 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
513 client->servername = servername[0] ? strdup(servername) : NULL;
515 /* We have the client already, update the data */
518 silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
520 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
523 SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOWAS reply "
525 hostname ? hostname : "", nick));
530 silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
531 if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128))
534 silc_free(client->nickname);
535 silc_free(client->username);
536 silc_free(client->servername);
538 client->nickname = strdup(nick);
539 client->username = strdup(username);
540 client->servername = servername[0] ? strdup(servername) : NULL;
541 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
542 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
544 /* Remove the old cache entry and create a new one */
545 silc_idcache_del_by_context(global ? server->global_list->clients :
546 server->local_list->clients, client, NULL);
547 silc_idcache_add(global ? server->global_list->clients :
548 server->local_list->clients, nickname, client->id,
555 /* Received reply for WHOWAS command. Cache the client information only for
556 a short period of time. */
558 SILC_SERVER_CMD_REPLY_FUNC(whowas)
560 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
561 SilcStatus status, error;
563 COMMAND_CHECK_STATUS;
565 if (!silc_server_command_reply_whowas_save(cmd))
568 /* Pending callbacks are not executed if this was an list entry */
569 if (status != SILC_STATUS_OK &&
570 status != SILC_STATUS_LIST_END) {
571 silc_server_command_reply_free(cmd);
576 silc_server_command_process_error(cmd, error);
577 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
578 silc_server_command_reply_free(cmd);
582 silc_server_command_process_error(cmd, error);
583 silc_server_command_reply_free(cmd);
586 /* Caches the received IDENTIFY information. */
589 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
591 SilcServer server = cmd->server;
592 SilcUInt32 len, id_len;
593 unsigned char *id_data;
595 SilcClientID client_id;
596 SilcServerID server_id;
597 SilcChannelID*channel_id;
598 SilcClientEntry client;
599 SilcServerEntry server_entry;
600 SilcChannelEntry channel;
603 SilcIDPayload idp = NULL;
606 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
609 idp = silc_id_payload_parse(id_data, id_len);
613 name = silc_argument_get_arg_type(cmd->args, 3, &len);
614 info = silc_argument_get_arg_type(cmd->args, 4, &len);
616 id_type = silc_id_payload_get_type(idp);
620 if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
623 SILC_LOG_DEBUG(("Received client information"));
625 client = silc_idlist_find_client_by_id(server->local_list,
626 &client_id, FALSE, NULL);
628 client = silc_idlist_find_client_by_id(server->global_list, &client_id,
633 /* If router did not find such Client ID in its lists then this must
634 be bogus client or some router in the net is buggy. */
635 if (server->server_type != SILC_SERVER)
640 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
642 /* We don't have that client anywhere, add it. The client is added
643 to global list since server didn't have it in the lists so it must be
645 client = silc_idlist_add_client(server->global_list,
646 nick[0] ? nick : NULL, info, NULL,
647 silc_id_dup(&client_id, SILC_ID_CLIENT),
648 silc_packet_get_context(cmd->sock),
651 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
655 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
656 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
657 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
659 /* We have the client already, update the data */
661 SILC_LOG_DEBUG(("Updating client data"));
665 silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
668 name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
671 SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY "
676 /* Remove the old cache entry */
677 silc_idcache_del_by_context(global ? server->global_list->clients :
678 server->local_list->clients, client, NULL);
680 silc_free(client->nickname);
681 client->nickname = strdup(nick);
683 /* Add new cache entry */
684 silc_idcache_add(global ? server->global_list->clients :
685 server->local_list->clients, name, client->id,
690 silc_free(client->username);
691 client->username = strdup(info);
694 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
695 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
704 if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
707 SILC_LOG_DEBUG(("Received server information"));
709 server_entry = silc_idlist_find_server_by_id(server->local_list,
710 &server_id, FALSE, NULL);
712 server_entry = silc_idlist_find_server_by_id(server->global_list,
713 &server_id, FALSE, NULL);
715 /* If router did not find such Server ID in its lists then this must
716 be bogus server or some router in the net is buggy. */
717 if (server->server_type != SILC_SERVER)
720 /* We don't have that server anywhere, add it. */
721 server_entry = silc_idlist_add_server(server->global_list,
723 silc_id_dup(&server_id,
726 SILC_PRIMARY_ROUTE(server));
730 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
731 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
732 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
737 case SILC_ID_CHANNEL:
741 if (!silc_id_payload_get_id(idp, &channel_id, sizeof(channel_id)))
744 SILC_LOG_DEBUG(("Received channel information"));
746 /* Check channel name */
747 info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
752 channel = silc_idlist_find_channel_by_name(server->local_list,
755 channel = silc_idlist_find_channel_by_name(server->global_list,
758 /* If router did not find such Channel ID in its lists then this must
759 be bogus channel or some router in the net is buggy. */
760 if (server->server_type != SILC_SERVER) {
765 /* We don't have that channel anywhere, add it. */
766 channel = silc_idlist_add_channel(server->global_list, strdup(name),
767 SILC_CHANNEL_MODE_NONE,
768 silc_id_dup(&channel_id,
770 server->router, NULL, NULL, 0);
781 silc_id_payload_free(idp);
785 silc_id_payload_free(idp);
789 /* Received reply for forwarded IDENTIFY command. We have received the
790 requested identify information now and we will cache it. After this we
791 will call the pending command so that the requestee gets the information
794 SILC_SERVER_CMD_REPLY_FUNC(identify)
796 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
797 SilcStatus status, error;
799 COMMAND_CHECK_STATUS;
801 if (!silc_server_command_reply_identify_save(cmd))
804 /* Pending callbacks are not executed if this was an list entry */
805 if (status != SILC_STATUS_OK &&
806 status != SILC_STATUS_LIST_END) {
807 silc_server_command_reply_free(cmd);
812 silc_server_command_process_error(cmd, error);
813 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
814 silc_server_command_reply_free(cmd);
818 silc_server_command_process_error(cmd, error);
819 silc_server_command_reply_free(cmd);
822 /* Received reply fro INFO command. Cache the server and its information */
824 SILC_SERVER_CMD_REPLY_FUNC(info)
826 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
827 SilcServer server = cmd->server;
828 SilcStatus status, error;
829 SilcServerEntry entry;
832 unsigned char *tmp, *name;
834 COMMAND_CHECK_STATUS;
837 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
841 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
845 entry = silc_idlist_find_server_by_id(server->local_list,
849 entry = silc_idlist_find_server_by_id(server->global_list,
853 /* Add the server to global list */
854 entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
855 silc_id_dup(SILC_ID_GET_ID(id),
857 silc_packet_get_context(cmd->sock),
862 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
866 /* Get the info string */
867 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
871 entry->server_info = tmp ? strdup(tmp) : NULL;
874 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
876 silc_server_command_reply_free(cmd);
879 /* Received reply fro MOTD command. */
881 SILC_SERVER_CMD_REPLY_FUNC(motd)
883 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
884 SilcServer server = cmd->server;
885 SilcStatus status, error;
886 SilcServerEntry entry = NULL;
891 COMMAND_CHECK_STATUS;
894 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
897 entry = silc_idlist_find_server_by_id(server->local_list,
901 entry = silc_idlist_find_server_by_id(server->global_list,
907 /* If router did not find such Server ID in its lists then this must
908 be bogus client or some router in the net is buggy. */
909 if (server->server_type != SILC_SERVER)
913 cmd->server->stat.commands_sent++;
915 /* entry isn't known so we IDENTIFY it. otherwise the
916 silc_server_command_motd won't know about it and tell
917 the client that there is no such server */
918 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
919 buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
920 ++server->cmd_ident, 5,
921 1, NULL, 0, 2, NULL, 0,
922 3, NULL, 0, 4, NULL, 0,
924 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
925 SILC_PACKET_COMMAND, 0, buffer->data,
926 silc_buffer_len(buffer));
927 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
929 silc_server_command_reply_motd,
931 silc_buffer_free(buffer);
937 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
944 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
946 silc_server_command_reply_free(cmd);
952 /* Received reply for forwarded JOIN command. Router has created or joined
953 the client to the channel. We save some channel information locally
956 SILC_SERVER_CMD_REPLY_FUNC(join)
958 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
959 SilcServer server = cmd->server;
960 SilcIDCacheEntry cache = NULL;
961 SilcStatus status, error;
963 SilcChannelEntry entry;
964 SilcHmac hmac = NULL;
965 SilcUInt32 len, list_count;
966 char *channel_name, *channel_namec = NULL, *tmp;
967 SilcUInt32 mode, created;
968 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
969 SilcPublicKey founder_key = NULL;
971 COMMAND_CHECK_STATUS;
973 /* Get channel name */
974 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
979 if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id, NULL))
983 if (!silc_argument_get_decoded(cmd->args, 4, SILC_ARGUMENT_ID, &id2, NULL))
987 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
990 SILC_GET32_MSB(mode, tmp);
992 /* Get created boolean value */
993 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
996 SILC_GET32_MSB(created, tmp);
997 if (created != 0 && created != 1)
1000 /* Get channel key */
1001 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
1003 keyp = silc_buffer_alloc(len);
1004 silc_buffer_pull_tail(keyp, silc_buffer_truelen(keyp));
1005 silc_buffer_put(keyp, tmp, len);
1009 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1011 if (!silc_hmac_alloc(tmp, NULL, &hmac))
1015 /* Get the list count */
1016 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1019 SILC_GET32_MSB(list_count, tmp);
1021 /* Get Client ID list */
1022 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1026 client_id_list = silc_buffer_alloc(len);
1027 silc_buffer_pull_tail(client_id_list, len);
1028 silc_buffer_put(client_id_list, tmp, len);
1030 /* Get client mode list */
1031 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1035 client_mode_list = silc_buffer_alloc(len);
1036 silc_buffer_pull_tail(client_mode_list, len);
1037 silc_buffer_put(client_mode_list, tmp, len);
1039 /* Get founder key */
1040 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1042 silc_public_key_payload_decode(tmp, len, &founder_key);
1044 /* See whether we already have the channel. */
1045 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
1046 SILC_STRING_UTF8, 256, NULL);
1049 entry = silc_idlist_find_channel_by_name(server->local_list,
1050 channel_namec, &cache);
1052 /* Add new channel */
1054 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1055 (created == 0 ? "existing" : "created"), channel_name,
1056 silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL)));
1058 /* If the channel is found from global list we must move it to the
1060 entry = silc_idlist_find_channel_by_name(server->global_list,
1061 channel_namec, &cache);
1063 silc_idlist_del_channel(server->global_list, entry);
1065 /* Add the channel to our local list. */
1066 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1067 SILC_CHANNEL_MODE_NONE,
1068 silc_id_dup(SILC_ID_GET_ID(id),
1070 server->router, NULL, NULL, hmac);
1075 server->stat.my_channels++;
1076 server->stat.channels++;
1078 /* The entry exists. */
1080 /* If ID has changed, then update it to the cache too. */
1081 if (!SILC_ID_CHANNEL_COMPARE(entry->id, SILC_ID_GET_ID(id)))
1082 silc_idlist_replace_channel_id(server->local_list, entry->id,
1083 SILC_ID_GET_ID(id));
1085 entry->disabled = FALSE;
1087 /* Remove the founder auth data if the mode is not set but we have
1088 them in the entry */
1089 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1090 silc_pkcs_public_key_free(entry->founder_key);
1091 entry->founder_key = NULL;
1096 if (entry->founder_key)
1097 silc_pkcs_public_key_free(entry->founder_key);
1098 entry->founder_key = founder_key;
1102 if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1103 silc_free(entry->hmac_name);
1104 entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1107 /* Get the ban list */
1108 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1109 if (tmp && len > 2) {
1110 SilcArgumentPayload iargs;
1112 SILC_GET16_MSB(iargc, tmp);
1113 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1115 /* Delete old ban list */
1116 if (entry->ban_list)
1117 silc_hash_table_free(entry->ban_list);
1119 silc_hash_table_alloc(0, silc_hash_ptr,
1121 silc_server_inviteban_destruct, entry, TRUE);
1123 /* Add new ban list */
1124 silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1125 silc_argument_payload_free(iargs);
1129 /* Get the invite list */
1130 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1131 if (tmp && len > 2) {
1132 SilcArgumentPayload iargs;
1134 SILC_GET16_MSB(iargc, tmp);
1135 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1137 /* Delete old invite list */
1138 if (entry->invite_list)
1139 silc_hash_table_free(entry->invite_list);
1140 entry->invite_list =
1141 silc_hash_table_alloc(0, silc_hash_ptr,
1143 silc_server_inviteban_destruct, entry, TRUE);
1145 /* Add new invite list */
1146 silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1147 silc_argument_payload_free(iargs);
1152 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1154 silc_free(entry->topic);
1155 entry->topic = strdup(tmp);
1158 /* Get channel public key list */
1159 tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1160 if (tmp && server->server_type != SILC_ROUTER)
1161 silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1163 /* The the user limit */
1164 tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1165 if (tmp && len == 4)
1166 SILC_GET32_MSB(entry->user_limit, tmp);
1168 /* If channel was not created we know there is global users on the
1170 entry->global_users = (created == 0 ? TRUE : FALSE);
1172 /* If channel was just created the mask must be zero */
1173 if (!entry->global_users && mode)
1176 /* Save channel mode */
1179 /* Save channel key */
1181 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1182 silc_server_save_channel_key(server, keyp, entry);
1183 silc_buffer_free(keyp);
1186 /* Save the users to the channel */
1187 silc_server_save_users_on_channel(server, cmd->sock, entry,
1188 SILC_ID_GET_ID(id2), client_id_list,
1189 client_mode_list, list_count);
1190 entry->users_resolved = TRUE;
1193 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1195 silc_free(channel_namec);
1197 silc_hmac_free(hmac);
1198 silc_server_command_reply_free(cmd);
1200 silc_pkcs_public_key_free(founder_key);
1202 silc_buffer_free(client_id_list);
1203 if (client_mode_list)
1204 silc_buffer_free(client_mode_list);
1207 /* Received reply to STATS command. */
1209 SILC_SERVER_CMD_REPLY_FUNC(stats)
1211 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1212 SilcServer server = cmd->server;
1213 SilcStatus status, error;
1216 SilcBufferStruct buf;
1218 COMMAND_CHECK_STATUS;
1220 /* Get statistics structure */
1221 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1222 if (server->server_type != SILC_ROUTER && tmp) {
1223 silc_buffer_set(&buf, tmp, tmp_len);
1224 silc_buffer_unformat(&buf,
1225 SILC_STR_UI_INT(NULL),
1226 SILC_STR_UI_INT(NULL),
1227 SILC_STR_UI_INT(NULL),
1228 SILC_STR_UI_INT(NULL),
1229 SILC_STR_UI_INT(NULL),
1230 SILC_STR_UI_INT(NULL),
1231 SILC_STR_UI_INT(&server->stat.cell_clients),
1232 SILC_STR_UI_INT(&server->stat.cell_channels),
1233 SILC_STR_UI_INT(&server->stat.cell_servers),
1234 SILC_STR_UI_INT(&server->stat.clients),
1235 SILC_STR_UI_INT(&server->stat.channels),
1236 SILC_STR_UI_INT(&server->stat.servers),
1237 SILC_STR_UI_INT(&server->stat.routers),
1238 SILC_STR_UI_INT(&server->stat.server_ops),
1239 SILC_STR_UI_INT(&server->stat.router_ops),
1244 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1246 silc_server_command_reply_free(cmd);
1249 SILC_SERVER_CMD_REPLY_FUNC(users)
1251 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1252 SilcServer server = cmd->server;
1253 SilcStatus status, error;
1254 SilcChannelEntry channel;
1256 SilcBuffer client_id_list;
1257 SilcBuffer client_mode_list;
1260 SilcUInt32 list_count;
1262 COMMAND_CHECK_STATUS;
1264 /* Get channel ID */
1265 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1268 /* Get channel entry */
1269 channel = silc_idlist_find_channel_by_id(server->local_list,
1270 SILC_ID_GET_ID(id), NULL);
1272 channel = silc_idlist_find_channel_by_id(server->global_list,
1273 SILC_ID_GET_ID(id), NULL);
1277 if (server->server_type != SILC_SERVER)
1280 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1281 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1282 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1283 1, 5, idp->data, silc_buffer_len(idp));
1284 silc_buffer_free(idp);
1286 /* Register pending command callback. After we've received the channel
1287 information we will reprocess this command reply by re-calling this
1288 USERS command reply callback. */
1289 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1291 silc_server_command_reply_users, cmd);
1296 /* Get the list count */
1297 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1300 SILC_GET32_MSB(list_count, tmp);
1302 /* Get Client ID list */
1303 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1307 client_id_list = silc_buffer_alloc(tmp_len);
1308 silc_buffer_pull_tail(client_id_list, tmp_len);
1309 silc_buffer_put(client_id_list, tmp, tmp_len);
1311 /* Get client mode list */
1312 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1316 client_mode_list = silc_buffer_alloc(tmp_len);
1317 silc_buffer_pull_tail(client_mode_list, tmp_len);
1318 silc_buffer_put(client_mode_list, tmp, tmp_len);
1320 /* Save the users to the channel */
1321 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1322 client_id_list, client_mode_list,
1325 channel->global_users = silc_server_channel_has_global(channel);
1326 channel->users_resolved = TRUE;
1328 silc_buffer_free(client_id_list);
1329 silc_buffer_free(client_mode_list);
1332 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1334 silc_server_command_reply_free(cmd);
1337 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1339 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1340 SilcServer server = cmd->server;
1341 SilcStatus status, error;
1342 SilcClientEntry client = NULL;
1343 SilcServerEntry server_entry = NULL;
1344 SilcClientID client_id;
1345 SilcServerID server_id;
1348 SilcIDPayload idp = NULL;
1350 SilcPublicKey public_key = NULL;
1352 COMMAND_CHECK_STATUS;
1354 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1357 idp = silc_id_payload_parse(tmp, len);
1361 /* Get the public key payload */
1362 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1366 /* Decode the public key payload */
1367 if (!silc_public_key_payload_decode(tmp, len, &public_key))
1370 id_type = silc_id_payload_get_type(idp);
1371 if (id_type == SILC_ID_CLIENT) {
1372 silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
1374 client = silc_idlist_find_client_by_id(server->local_list, &client_id,
1377 client = silc_idlist_find_client_by_id(server->global_list,
1378 &client_id, TRUE, NULL);
1383 if (!client->data.public_key) {
1384 if (!silc_hash_table_find_by_context(server->pk_hash, public_key,
1386 silc_hash_table_add(server->pk_hash, public_key, client);
1388 client->data.public_key = public_key;
1391 } else if (id_type == SILC_ID_SERVER) {
1392 silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
1394 server_entry = silc_idlist_find_server_by_id(server->local_list,
1395 &server_id, TRUE, NULL);
1396 if (!server_entry) {
1397 server_entry = silc_idlist_find_server_by_id(server->global_list,
1398 &server_id, TRUE, NULL);
1403 server_entry->data.public_key = public_key;
1410 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1412 silc_id_payload_free(idp);
1414 silc_pkcs_public_key_free(public_key);
1416 silc_server_command_reply_free(cmd);
1419 SILC_SERVER_CMD_REPLY_FUNC(list)
1421 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1422 SilcServer server = cmd->server;
1423 SilcStatus status, error;
1425 SilcChannelEntry channel;
1426 SilcIDCacheEntry cache;
1427 unsigned char *tmp, *name, *namec = NULL, *topic;
1428 SilcUInt32 usercount = 0;
1429 SilcBool global_list = FALSE;
1431 COMMAND_CHECK_STATUS;
1433 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1436 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1437 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1438 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1440 SILC_GET32_MSB(usercount, tmp);
1442 namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
1447 /* Add the channel entry if we do not have it already */
1448 channel = silc_idlist_find_channel_by_name(server->local_list,
1451 channel = silc_idlist_find_channel_by_name(server->global_list,
1456 /* If router did not find such channel in its lists then this must
1457 be bogus channel or some router in the net is buggy. */
1458 if (server->server_type != SILC_SERVER)
1461 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1462 SILC_CHANNEL_MODE_NONE,
1463 silc_id_dup(SILC_ID_GET_ID(id),
1465 server->router, NULL, NULL, NULL);
1470 channel->user_count = usercount;
1473 silc_free(channel->topic);
1474 channel->topic = strdup(topic);
1477 /* Pending callbacks are not executed if this was an list entry */
1478 if (status != SILC_STATUS_OK &&
1479 status != SILC_STATUS_LIST_END) {
1480 silc_server_command_reply_free(cmd);
1485 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1488 silc_server_command_reply_free(cmd);
1491 SILC_SERVER_CMD_REPLY_FUNC(watch)
1493 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1494 SilcStatus status, error;
1496 COMMAND_CHECK_STATUS;
1499 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1501 silc_server_command_reply_free(cmd);
1504 SILC_SERVER_CMD_REPLY_FUNC(ping)
1506 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1507 SilcStatus status, error;
1509 COMMAND_CHECK_STATUS;
1512 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1514 silc_server_command_reply_free(cmd);