5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 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);
151 if (client->data.public_key)
152 silc_hash_table_del_by_context(server->pk_hash,
153 client->data.public_key,
156 silc_server_remove_from_channels(server, NULL, client, TRUE,
158 silc_idlist_del_data(client);
159 silc_idlist_del_client(server->global_list, client);
161 silc_free(client_id);
167 /* Caches the received WHOIS information. */
170 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
172 SilcServer server = cmd->server;
173 unsigned char *id_data, *umodes;
174 char *nickname, *username, *realname, *tmp, *servername = NULL;
175 unsigned char *fingerprint;
176 SilcClientID *client_id;
177 SilcClientEntry client;
178 SilcIDCacheEntry cache = NULL;
181 SilcUInt32 mode = 0, len, len2, id_len, flen;
183 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
184 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
185 username = silc_argument_get_arg_type(cmd->args, 4, &len);
186 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
187 if (!id_data || !nickname || !username || !realname)
190 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
192 SILC_GET32_MSB(mode, tmp);
194 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
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, client_id,
205 client = silc_idlist_find_client_by_id(server->global_list, client_id,
211 /* If router did not find such Client ID in its lists then this must
212 be bogus client or some router in the net is buggy. */
213 if (server->server_type != SILC_SERVER)
216 /* Take hostname out of nick string if it includes it. */
217 silc_parse_userfqdn(nickname, &nick, &servername);
219 /* We don't have that client anywhere, add it. The client is added
220 to global list since server didn't have it in the lists so it must be
221 global. This will check for valid nickname and username strings. */
222 client = silc_idlist_add_client(server->global_list, nick, username,
223 strdup(realname), client_id,
224 cmd->sock->user_data, NULL, 0);
226 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
228 silc_free(servername);
232 client->data.status |=
233 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
234 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
236 client->servername = servername;
238 /* We have the client already, update the data */
240 SILC_LOG_DEBUG(("Updating client data"));
243 silc_parse_userfqdn(nickname, &nick, &servername);
244 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
247 SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOIS reply "
249 cmd->sock->hostname ? cmd->sock->hostname : "", nick));
251 silc_free(servername);
256 silc_parse_userfqdn(username, &tmp, NULL);
257 if (!silc_identifier_verify(tmp, strlen(tmp), SILC_STRING_UTF8, 128)) {
260 silc_free(servername);
261 SILC_LOG_ERROR(("Malformed username '%s' received in WHOIS reply "
263 cmd->sock->hostname ? cmd->sock->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);
272 silc_free(client->nickname);
273 silc_free(client->username);
274 silc_free(client->userinfo);
275 silc_free(client->servername);
277 client->nickname = nick;
278 client->username = strdup(username);
279 client->userinfo = strdup(realname);
280 client->servername = servername;
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,
289 silc_free(client_id);
292 /* Save channel list if it was sent to us */
293 if (server->server_type == SILC_SERVER) {
294 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
295 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
297 SilcBufferStruct channels_buf, umodes_buf;
298 silc_buffer_set(&channels_buf, tmp, len);
299 silc_buffer_set(&umodes_buf, umodes, len2);
300 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
303 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
306 /* If client is global and is not on any channel then add that we'll
307 expire the entry after a while. */
309 silc_idlist_find_client_by_id(server->global_list, client->id,
311 if (!silc_hash_table_count(client->channels))
312 cache->expire = time(NULL) + 300;
318 if (fingerprint && flen == sizeof(client->data.fingerprint))
319 memcpy(client->data.fingerprint, fingerprint, flen);
321 /* Take Requested Attributes if set. */
322 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
324 silc_free(client->attrs);
325 client->attrs = silc_memdup(tmp, len);
326 client->attrs_len = len;
328 /* Try to take public key from attributes if present and we don't have
329 the key already. Do this only on normal server. Routers do GETKEY
330 for all clients anyway. */
331 if (server->server_type != SILC_ROUTER && !client->data.public_key) {
332 SilcAttributePayload attr;
333 SilcAttributeObjPk pk;
334 unsigned char f[SILC_HASH_MAXLEN];
335 SilcDList attrs = silc_attribute_payload_parse(tmp, len);
337 SILC_LOG_DEBUG(("Take client public key from attributes"));
340 silc_dlist_start(attrs);
341 while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
342 if (silc_attribute_get_attribute(attr) ==
343 SILC_ATTRIBUTE_USER_PUBLIC_KEY) {
345 if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
348 /* Take only SILC public keys */
349 if (strcmp(pk.type, "silc-rsa")) {
355 /* Verify that the server provided fingerprint matches the key */
356 silc_hash_make(server->sha1hash, pk.data, pk.data_len, f);
357 if (memcmp(f, client->data.fingerprint, sizeof(f))) {
363 /* Save the public key. */
364 if (!silc_pkcs_public_key_decode(pk.data, pk.data_len,
365 &client->data.public_key)) {
371 SILC_LOG_DEBUG(("Saved client public key from attributes"));
373 /* Add to public key hash table */
374 if (!silc_hash_table_find_by_context(server->pk_hash,
375 client->data.public_key,
377 silc_hash_table_add(server->pk_hash,
378 client->data.public_key, client);
386 silc_attribute_payload_list_free(attrs);
394 /* Handle requested attributes reply in WHOIS from client */
397 silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd)
401 SilcClientEntry client = cmd->sock->user_data;
403 /* Take Requested Attributes if set. */
404 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
406 silc_free(client->attrs);
407 client->attrs = silc_memdup(tmp, len);
408 client->attrs_len = len;
411 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
416 /* Reiceved reply for WHOIS command. We sent the whois request to our
417 primary router, if we are normal server, and thus has now received reply
418 to the command. We will figure out what client originally sent us the
419 command and will send the reply to it. If we are router we will figure
420 out who server sent us the command and send reply to that one. */
422 SILC_SERVER_CMD_REPLY_FUNC(whois)
424 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
425 SilcStatus status, error;
427 COMMAND_CHECK_STATUS;
429 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) {
430 if (!silc_server_command_reply_whois_save(cmd))
433 if (!silc_server_command_reply_whois_save_client(cmd))
437 /* Pending callbacks are not executed if this was an list entry */
438 if (status != SILC_STATUS_OK &&
439 status != SILC_STATUS_LIST_END) {
440 silc_server_command_reply_free(cmd);
445 silc_server_command_process_error(cmd, error);
446 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
447 silc_server_command_reply_free(cmd);
451 silc_server_command_process_error(cmd, error);
452 silc_server_command_reply_free(cmd);
455 /* Caches the received WHOWAS information for a short period of time. */
458 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
460 SilcServer server = cmd->server;
461 SilcUInt32 len, id_len;
462 unsigned char *id_data;
463 char *nickname, *username, *realname, *servername = NULL, *tmp;
464 SilcClientID *client_id;
465 SilcClientEntry client;
466 SilcIDCacheEntry cache = NULL;
470 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
471 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
472 username = silc_argument_get_arg_type(cmd->args, 4, &len);
473 if (!id_data || !nickname || !username)
476 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
478 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
482 /* Check if we have this client cached already. */
484 client = silc_idlist_find_client_by_id(server->local_list, client_id,
487 client = silc_idlist_find_client_by_id(server->global_list,
488 client_id, FALSE, &cache);
493 /* If router did not find such Client ID in its lists then this must
494 be bogus client or some router in the net is buggy. */
495 if (server->server_type != SILC_SERVER)
498 /* Take hostname out of nick string if it includes it. */
499 silc_parse_userfqdn(nickname, &nick, &servername);
501 /* We don't have that client anywhere, add it. The client is added
502 to global list since server didn't have it in the lists so it must be
504 client = silc_idlist_add_client(server->global_list, nick, username,
506 silc_id_dup(client_id, SILC_ID_CLIENT),
507 cmd->sock->user_data, NULL,
508 SILC_ID_CACHE_EXPIRE_DEF);
510 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
512 silc_free(servername);
516 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
517 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
518 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
519 client->servername = servername;
521 /* We have the client already, update the data */
524 silc_parse_userfqdn(nickname, &nick, &servername);
525 nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
528 SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOWAS reply "
530 cmd->sock->hostname ? cmd->sock->hostname : "", nick));
532 silc_free(servername);
537 silc_parse_userfqdn(username, &tmp, NULL);
538 if (!silc_identifier_verify(tmp, strlen(tmp), SILC_STRING_UTF8, 128)) {
541 silc_free(servername);
542 SILC_LOG_ERROR(("Malformed username '%s' received in WHOWAS reply "
544 cmd->sock->hostname ? cmd->sock->hostname : "", tmp));
549 silc_free(client->nickname);
550 silc_free(client->username);
551 silc_free(client->servername);
553 client->nickname = nick;
554 client->username = strdup(username);
555 client->servername = servername;
556 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
557 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
559 /* Remove the old cache entry and create a new one */
560 silc_idcache_del_by_context(global ? server->global_list->clients :
561 server->local_list->clients, client);
562 silc_idcache_add(global ? server->global_list->clients :
563 server->local_list->clients, nickname, client->id,
567 /* If client is global and is not on any channel then add that we'll
568 expire the entry after a while. */
570 silc_idlist_find_client_by_id(server->global_list, client->id,
572 if (!silc_hash_table_count(client->channels))
573 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
578 silc_free(client_id);
583 /* Received reply for WHOWAS command. Cache the client information only for
584 a short period of time. */
586 SILC_SERVER_CMD_REPLY_FUNC(whowas)
588 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
589 SilcStatus status, error;
591 COMMAND_CHECK_STATUS;
593 if (!silc_server_command_reply_whowas_save(cmd))
596 /* Pending callbacks are not executed if this was an list entry */
597 if (status != SILC_STATUS_OK &&
598 status != SILC_STATUS_LIST_END) {
599 silc_server_command_reply_free(cmd);
604 silc_server_command_process_error(cmd, error);
605 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
606 silc_server_command_reply_free(cmd);
610 silc_server_command_process_error(cmd, error);
611 silc_server_command_reply_free(cmd);
614 /* Caches the received IDENTIFY information. */
617 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
619 SilcServer server = cmd->server;
620 SilcUInt32 len, id_len;
621 unsigned char *id_data;
623 SilcClientID *client_id = NULL;
624 SilcServerID *server_id = NULL;
625 SilcChannelID *channel_id = NULL;
626 SilcClientEntry client;
627 SilcServerEntry server_entry;
628 SilcChannelEntry channel;
631 SilcIDPayload idp = NULL;
635 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
638 idp = silc_id_payload_parse(id_data, id_len);
642 name = silc_argument_get_arg_type(cmd->args, 3, &len);
643 info = silc_argument_get_arg_type(cmd->args, 4, &len);
645 id_type = silc_id_payload_get_type(idp);
649 client_id = silc_id_payload_get_id(idp);
653 SILC_LOG_DEBUG(("Received client information"));
655 client = silc_idlist_find_client_by_id(server->local_list,
656 client_id, FALSE, NULL);
658 client = silc_idlist_find_client_by_id(server->global_list, client_id,
663 /* If router did not find such Client ID in its lists then this must
664 be bogus client or some router in the net is buggy. */
665 if (server->server_type != SILC_SERVER)
670 silc_parse_userfqdn(name, &nick, NULL);
672 /* We don't have that client anywhere, add it. The client is added
673 to global list since server didn't have it in the lists so it must be
675 client = silc_idlist_add_client(server->global_list, nick, info, NULL,
676 client_id, cmd->sock->user_data,
677 NULL, time(NULL) + 300);
679 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
684 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
685 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
686 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
688 /* We have the client already, update the data */
690 SILC_LOG_DEBUG(("Updating client data"));
694 silc_parse_userfqdn(name, &nick, NULL);
697 name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
700 SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY reply "
702 cmd->sock->hostname ?
703 cmd->sock->hostname : "", nick));
707 /* Remove the old cache entry */
708 silc_idcache_del_by_context(global ? server->global_list->clients :
709 server->local_list->clients, client);
711 silc_free(client->nickname);
712 client->nickname = nick;
714 /* Add new cache entry */
715 silc_idcache_add(global ? server->global_list->clients :
716 server->local_list->clients, name, client->id,
717 client, expire, NULL);
721 silc_free(client->username);
722 client->username = strdup(info);
725 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
726 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
728 /* If client is global and is not on any channel then add that we'll
729 expire the entry after a while. */
730 if (global && server->server_type == SILC_SERVER) {
731 SilcIDCacheEntry cache = NULL;
732 silc_idlist_find_client_by_id(server->global_list, client->id,
734 if (!silc_hash_table_count(client->channels))
735 cache->expire = time(NULL) + 300;
740 silc_free(client_id);
749 server_id = silc_id_payload_get_id(idp);
753 SILC_LOG_DEBUG(("Received server information"));
755 server_entry = silc_idlist_find_server_by_id(server->local_list,
756 server_id, FALSE, NULL);
758 server_entry = silc_idlist_find_server_by_id(server->global_list,
759 server_id, FALSE, NULL);
761 /* If router did not find such Server ID in its lists then this must
762 be bogus server or some router in the net is buggy. */
763 if (server->server_type != SILC_SERVER)
766 /* We don't have that server anywhere, add it. */
767 server_entry = silc_idlist_add_server(server->global_list,
769 server_id, server->router,
770 SILC_PRIMARY_ROUTE(server));
772 silc_free(server_id);
775 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
776 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
777 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
781 silc_free(server_id);
784 case SILC_ID_CHANNEL:
788 channel_id = silc_id_payload_get_id(idp);
792 SILC_LOG_DEBUG(("Received channel information"));
794 /* Check channel name */
795 info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
800 channel = silc_idlist_find_channel_by_name(server->local_list,
803 channel = silc_idlist_find_channel_by_name(server->global_list,
806 /* If router did not find such Channel ID in its lists then this must
807 be bogus channel or some router in the net is buggy. */
808 if (server->server_type != SILC_SERVER) {
813 /* We don't have that channel anywhere, add it. */
814 channel = silc_idlist_add_channel(server->global_list, strdup(name),
815 SILC_CHANNEL_MODE_NONE, channel_id,
816 server->router, NULL, NULL, 0);
818 silc_free(channel_id);
826 silc_free(channel_id);
830 silc_id_payload_free(idp);
834 silc_id_payload_free(idp);
838 /* Received reply for forwarded IDENTIFY command. We have received the
839 requested identify information now and we will cache it. After this we
840 will call the pending command so that the requestee gets the information
843 SILC_SERVER_CMD_REPLY_FUNC(identify)
845 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
846 SilcStatus status, error;
848 COMMAND_CHECK_STATUS;
850 if (!silc_server_command_reply_identify_save(cmd))
853 /* Pending callbacks are not executed if this was an list entry */
854 if (status != SILC_STATUS_OK &&
855 status != SILC_STATUS_LIST_END) {
856 silc_server_command_reply_free(cmd);
861 silc_server_command_process_error(cmd, error);
862 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
863 silc_server_command_reply_free(cmd);
867 silc_server_command_process_error(cmd, error);
868 silc_server_command_reply_free(cmd);
871 /* Received reply fro INFO command. Cache the server and its information */
873 SILC_SERVER_CMD_REPLY_FUNC(info)
875 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
876 SilcServer server = cmd->server;
877 SilcStatus status, error;
878 SilcServerEntry entry;
879 SilcServerID *server_id;
881 unsigned char *tmp, *name;
883 COMMAND_CHECK_STATUS;
886 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
889 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
894 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
898 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
901 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
904 /* Add the server to global list */
905 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
906 entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
907 server_id, cmd->sock->user_data,
910 silc_free(server_id);
913 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
917 /* Get the info string */
918 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
922 entry->server_info = tmp ? strdup(tmp) : NULL;
925 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
927 silc_server_command_reply_free(cmd);
930 /* Received reply fro MOTD command. */
932 SILC_SERVER_CMD_REPLY_FUNC(motd)
934 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
935 SilcServer server = cmd->server;
936 SilcStatus status, error;
937 SilcServerEntry entry = NULL;
938 SilcServerID *server_id;
942 COMMAND_CHECK_STATUS;
945 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
948 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
952 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
955 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
960 /* If router did not find such Server ID in its lists then this must
961 be bogus client or some router in the net is buggy. */
962 if (server->server_type != SILC_SERVER)
966 cmd->server->stat.commands_sent++;
968 /* entry isn't known so we IDENTIFY it. otherwise the
969 silc_server_command_motd won't know about it and tell
970 the client that there is no such server */
971 buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
972 ++server->cmd_ident, 5,
973 1, NULL, 0, 2, NULL, 0,
974 3, NULL, 0, 4, NULL, 0,
976 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
977 SILC_PACKET_COMMAND, 0, buffer->data,
979 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
981 silc_server_command_reply_motd,
983 silc_buffer_free(buffer);
989 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
996 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
998 silc_server_command_reply_free(cmd);
1004 /* Received reply for forwarded JOIN command. Router has created or joined
1005 the client to the channel. We save some channel information locally
1008 SILC_SERVER_CMD_REPLY_FUNC(join)
1010 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1011 SilcServer server = cmd->server;
1012 SilcIDCacheEntry cache = NULL;
1013 SilcStatus status, error;
1015 SilcClientID *client_id = NULL;
1016 SilcChannelEntry entry;
1017 SilcHmac hmac = NULL;
1018 SilcUInt32 id_len, len, list_count;
1019 unsigned char *id_string;
1020 char *channel_name, *channel_namec = NULL, *tmp;
1021 SilcUInt32 mode, created;
1022 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
1023 SilcPublicKey founder_key = NULL;
1025 COMMAND_CHECK_STATUS;
1027 /* Get channel name */
1028 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
1032 /* Get channel ID */
1033 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
1038 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
1041 client_id = silc_id_payload_parse_id(tmp, len, NULL);
1046 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1049 SILC_GET32_MSB(mode, tmp);
1051 /* Get created boolean value */
1052 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1055 SILC_GET32_MSB(created, tmp);
1056 if (created != 0 && created != 1)
1059 /* Get channel key */
1060 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
1062 keyp = silc_buffer_alloc(len);
1063 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
1064 silc_buffer_put(keyp, tmp, len);
1067 /* Parse the Channel ID */
1068 id = silc_id_payload_parse_id(id_string, id_len, NULL);
1073 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1075 if (!silc_hmac_alloc(tmp, NULL, &hmac))
1079 /* Get the list count */
1080 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1083 SILC_GET32_MSB(list_count, tmp);
1085 /* Get Client ID list */
1086 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1090 client_id_list = silc_buffer_alloc(len);
1091 silc_buffer_pull_tail(client_id_list, len);
1092 silc_buffer_put(client_id_list, tmp, len);
1094 /* Get client mode list */
1095 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1099 client_mode_list = silc_buffer_alloc(len);
1100 silc_buffer_pull_tail(client_mode_list, len);
1101 silc_buffer_put(client_mode_list, tmp, len);
1103 /* Get founder key */
1104 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1106 silc_pkcs_public_key_payload_decode(tmp, len, &founder_key);
1108 /* See whether we already have the channel. */
1109 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
1110 SILC_STRING_UTF8, 256, NULL);
1113 entry = silc_idlist_find_channel_by_name(server->local_list,
1114 channel_namec, &cache);
1116 /* Add new channel */
1118 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1119 (created == 0 ? "existing" : "created"), channel_name,
1120 silc_id_render(id, SILC_ID_CHANNEL)));
1122 /* If the channel is found from global list we must move it to the
1124 entry = silc_idlist_find_channel_by_name(server->global_list,
1125 channel_namec, &cache);
1127 silc_idlist_del_channel(server->global_list, entry);
1129 /* Add the channel to our local list. */
1130 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1131 SILC_CHANNEL_MODE_NONE, id,
1132 server->router, NULL, hmac, 0);
1138 server->stat.my_channels++;
1139 server->stat.channels++;
1141 /* The entry exists. */
1143 /* If ID has changed, then update it to the cache too. */
1144 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
1145 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
1147 entry->disabled = FALSE;
1149 /* Remove the founder auth data if the mode is not set but we have
1150 them in the entry */
1151 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1152 silc_pkcs_public_key_free(entry->founder_key);
1153 entry->founder_key = NULL;
1158 if (entry->founder_key)
1159 silc_pkcs_public_key_free(entry->founder_key);
1160 entry->founder_key = founder_key;
1164 if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1165 silc_free(entry->hmac_name);
1166 entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1169 /* Get the ban list */
1170 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1171 if (tmp && len > 2) {
1172 SilcArgumentPayload iargs;
1174 SILC_GET16_MSB(iargc, tmp);
1175 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1177 /* Delete old ban list */
1178 if (entry->ban_list)
1179 silc_hash_table_free(entry->ban_list);
1181 silc_hash_table_alloc(0, silc_hash_ptr,
1183 silc_server_inviteban_destruct, entry, TRUE);
1185 /* Add new ban list */
1186 silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1187 silc_argument_payload_free(iargs);
1191 /* Get the invite list */
1192 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1193 if (tmp && len > 2) {
1194 SilcArgumentPayload iargs;
1196 SILC_GET16_MSB(iargc, tmp);
1197 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1199 /* Delete old invite list */
1200 if (entry->invite_list)
1201 silc_hash_table_free(entry->invite_list);
1202 entry->invite_list =
1203 silc_hash_table_alloc(0, silc_hash_ptr,
1205 silc_server_inviteban_destruct, entry, TRUE);
1207 /* Add new invite list */
1208 silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1209 silc_argument_payload_free(iargs);
1214 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1216 silc_free(entry->topic);
1217 entry->topic = strdup(tmp);
1220 /* Get channel public key list */
1221 tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1222 if (tmp && server->server_type != SILC_ROUTER)
1223 silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1225 /* The the user limit */
1226 tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1227 if (tmp && len == 4)
1228 SILC_GET32_MSB(entry->user_limit, tmp);
1230 /* If channel was not created we know there is global users on the
1232 entry->global_users = (created == 0 ? TRUE : FALSE);
1234 /* If channel was just created the mask must be zero */
1235 if (!entry->global_users && mode) {
1236 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
1237 "new channel, forcing it to zero", cmd->sock->hostname));
1241 /* Save channel mode */
1244 /* Save channel key */
1246 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1247 silc_server_save_channel_key(server, keyp, entry);
1248 silc_buffer_free(keyp);
1251 /* Save the users to the channel */
1252 silc_server_save_users_on_channel(server, cmd->sock, entry,
1253 client_id, client_id_list,
1254 client_mode_list, list_count);
1255 entry->users_resolved = TRUE;
1258 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1260 silc_free(channel_namec);
1262 silc_hmac_free(hmac);
1263 silc_free(client_id);
1264 silc_server_command_reply_free(cmd);
1266 silc_pkcs_public_key_free(founder_key);
1268 silc_buffer_free(client_id_list);
1269 if (client_mode_list)
1270 silc_buffer_free(client_mode_list);
1273 /* Received reply to STATS command. */
1275 SILC_SERVER_CMD_REPLY_FUNC(stats)
1277 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1278 SilcServer server = cmd->server;
1279 SilcStatus status, error;
1282 SilcBufferStruct buf;
1284 COMMAND_CHECK_STATUS;
1286 /* Get statistics structure */
1287 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1288 if (server->server_type != SILC_ROUTER && tmp) {
1289 silc_buffer_set(&buf, tmp, tmp_len);
1290 silc_buffer_unformat(&buf,
1291 SILC_STR_UI_INT(NULL),
1292 SILC_STR_UI_INT(NULL),
1293 SILC_STR_UI_INT(NULL),
1294 SILC_STR_UI_INT(NULL),
1295 SILC_STR_UI_INT(NULL),
1296 SILC_STR_UI_INT(NULL),
1297 SILC_STR_UI_INT(&server->stat.cell_clients),
1298 SILC_STR_UI_INT(&server->stat.cell_channels),
1299 SILC_STR_UI_INT(&server->stat.cell_servers),
1300 SILC_STR_UI_INT(&server->stat.clients),
1301 SILC_STR_UI_INT(&server->stat.channels),
1302 SILC_STR_UI_INT(&server->stat.servers),
1303 SILC_STR_UI_INT(&server->stat.routers),
1304 SILC_STR_UI_INT(&server->stat.server_ops),
1305 SILC_STR_UI_INT(&server->stat.router_ops),
1310 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1312 silc_server_command_reply_free(cmd);
1315 SILC_SERVER_CMD_REPLY_FUNC(users)
1317 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1318 SilcServer server = cmd->server;
1319 SilcStatus status, error;
1320 SilcChannelEntry channel;
1321 SilcChannelID *channel_id = NULL;
1322 SilcBuffer client_id_list;
1323 SilcBuffer client_mode_list;
1326 SilcUInt32 list_count;
1328 COMMAND_CHECK_STATUS;
1330 /* Get channel ID */
1331 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1334 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1338 /* Get channel entry */
1339 channel = silc_idlist_find_channel_by_id(server->local_list,
1342 channel = silc_idlist_find_channel_by_id(server->global_list,
1347 if (server->server_type != SILC_SERVER)
1350 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1351 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1352 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1353 1, 5, idp->data, idp->len);
1354 silc_buffer_free(idp);
1356 /* Register pending command callback. After we've received the channel
1357 information we will reprocess this command reply by re-calling this
1358 USERS command reply callback. */
1359 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1361 silc_server_command_reply_users, cmd);
1366 /* Get the list count */
1367 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1370 SILC_GET32_MSB(list_count, tmp);
1372 /* Get Client ID list */
1373 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1377 client_id_list = silc_buffer_alloc(tmp_len);
1378 silc_buffer_pull_tail(client_id_list, tmp_len);
1379 silc_buffer_put(client_id_list, tmp, tmp_len);
1381 /* Get client mode list */
1382 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1386 client_mode_list = silc_buffer_alloc(tmp_len);
1387 silc_buffer_pull_tail(client_mode_list, tmp_len);
1388 silc_buffer_put(client_mode_list, tmp, tmp_len);
1390 /* Save the users to the channel */
1391 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1392 client_id_list, client_mode_list,
1395 channel->global_users = silc_server_channel_has_global(channel);
1396 channel->users_resolved = TRUE;
1398 silc_buffer_free(client_id_list);
1399 silc_buffer_free(client_mode_list);
1402 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1403 silc_free(channel_id);
1405 silc_server_command_reply_free(cmd);
1408 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1410 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1411 SilcServer server = cmd->server;
1412 SilcStatus status, error;
1413 SilcClientEntry client = NULL;
1414 SilcServerEntry server_entry = NULL;
1415 SilcClientID *client_id = NULL;
1416 SilcServerID *server_id = NULL;
1419 SilcIDPayload idp = NULL;
1421 SilcPublicKey public_key = NULL;
1423 COMMAND_CHECK_STATUS;
1425 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1428 idp = silc_id_payload_parse(tmp, len);
1432 /* Get the public key payload */
1433 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1437 /* Decode the public key payload */
1438 if (!silc_pkcs_public_key_payload_decode(tmp, len, &public_key))
1441 id_type = silc_id_payload_get_type(idp);
1442 if (id_type == SILC_ID_CLIENT) {
1443 client_id = silc_id_payload_get_id(idp);
1445 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1448 client = silc_idlist_find_client_by_id(server->global_list,
1449 client_id, TRUE, NULL);
1454 if (!client->data.public_key) {
1455 if (!silc_hash_table_find_by_context(server->pk_hash, public_key,
1457 silc_hash_table_add(server->pk_hash, public_key, client);
1459 client->data.public_key = public_key;
1462 } else if (id_type == SILC_ID_SERVER) {
1463 server_id = silc_id_payload_get_id(idp);
1465 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1467 if (!server_entry) {
1468 server_entry = silc_idlist_find_server_by_id(server->global_list,
1469 server_id, TRUE, NULL);
1474 server_entry->data.public_key = public_key;
1481 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1483 silc_id_payload_free(idp);
1484 silc_free(client_id);
1485 silc_free(server_id);
1487 silc_pkcs_public_key_free(public_key);
1489 silc_server_command_reply_free(cmd);
1492 SILC_SERVER_CMD_REPLY_FUNC(list)
1494 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1495 SilcServer server = cmd->server;
1496 SilcStatus status, error;
1497 SilcChannelID *channel_id = NULL;
1498 SilcChannelEntry channel;
1499 SilcIDCacheEntry cache;
1501 unsigned char *tmp, *name, *namec = NULL, *topic;
1502 SilcUInt32 usercount = 0;
1503 bool global_list = FALSE;
1505 COMMAND_CHECK_STATUS;
1507 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1510 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1514 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1515 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1516 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1518 SILC_GET32_MSB(usercount, tmp);
1520 namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
1525 /* Add the channel entry if we do not have it already */
1526 channel = silc_idlist_find_channel_by_name(server->local_list,
1529 channel = silc_idlist_find_channel_by_name(server->global_list,
1534 /* If router did not find such channel in its lists then this must
1535 be bogus channel or some router in the net is buggy. */
1536 if (server->server_type != SILC_SERVER)
1539 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1540 SILC_CHANNEL_MODE_NONE, channel_id,
1541 server->router, NULL, NULL,
1547 /* Found, update expiry */
1548 if (global_list && server->server_type == SILC_SERVER)
1549 cache->expire = time(NULL) + 60;
1552 channel->user_count = usercount;
1555 silc_free(channel->topic);
1556 channel->topic = strdup(topic);
1559 /* Pending callbacks are not executed if this was an list entry */
1560 if (status != SILC_STATUS_OK &&
1561 status != SILC_STATUS_LIST_END) {
1562 silc_server_command_reply_free(cmd);
1566 /* Now purge all old entries from the global list, otherwise we'll might
1567 have non-existent entries for long periods of time in the cache. */
1568 silc_idcache_purge(server->global_list->channels);
1571 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1572 silc_free(channel_id);
1575 silc_server_command_reply_free(cmd);
1578 SILC_SERVER_CMD_REPLY_FUNC(watch)
1580 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1581 SilcStatus status, error;
1583 COMMAND_CHECK_STATUS;
1586 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1588 silc_server_command_reply_free(cmd);
1591 SILC_SERVER_CMD_REPLY_FUNC(ping)
1593 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1594 SilcStatus status, error;
1596 COMMAND_CHECK_STATUS;
1599 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1601 silc_server_command_reply_free(cmd);