5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2004 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 *tmp, *id_data, *umodes;
174 char *nickname, *username, *realname, *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
222 client = silc_idlist_add_client(server->global_list, nick,
224 strdup(realname), client_id,
225 cmd->sock->user_data, NULL, 0);
227 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
231 client->data.status |=
232 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
233 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
235 client->servername = servername;
237 /* We have the client already, update the data */
239 SILC_LOG_DEBUG(("Updating client data"));
241 /* Take hostname out of nick string if it includes it. */
242 silc_parse_userfqdn(nickname, &nick, &servername);
244 /* Remove the old cache entry */
245 silc_idcache_del_by_context(global ? server->global_list->clients :
246 server->local_list->clients, client);
248 silc_free(client->nickname);
249 silc_free(client->username);
250 silc_free(client->userinfo);
251 silc_free(client->servername);
253 client->nickname = nick;
254 client->username = strdup(username);
255 client->userinfo = strdup(realname);
256 client->servername = servername;
258 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
259 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
261 /* Create new cache entry */
262 silc_idcache_add(global ? server->global_list->clients :
263 server->local_list->clients, nick, client->id,
265 silc_free(client_id);
268 /* Save channel list if it was sent to us */
269 if (server->server_type == SILC_SERVER) {
270 tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
271 umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
273 SilcBufferStruct channels_buf, umodes_buf;
274 silc_buffer_set(&channels_buf, tmp, len);
275 silc_buffer_set(&umodes_buf, umodes, len2);
276 silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
279 silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
282 /* If client is global and is not on any channel then add that we'll
283 expire the entry after a while. */
285 silc_idlist_find_client_by_id(server->global_list, client->id,
287 if (!silc_hash_table_count(client->channels))
288 cache->expire = time(NULL) + 300;
294 if (fingerprint && flen == sizeof(client->data.fingerprint))
295 memcpy(client->data.fingerprint, fingerprint, flen);
297 /* Take Requested Attributes if set. */
298 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
300 silc_free(client->attrs);
301 client->attrs = silc_memdup(tmp, len);
302 client->attrs_len = len;
304 /* Try to take public key from attributes if present and we don't have
305 the key already. Do this only on normal server. Routers do GETKEY
306 for all clients anyway. */
307 if (server->server_type != SILC_ROUTER && !client->data.public_key) {
308 SilcAttributePayload attr;
309 SilcAttributeObjPk pk;
311 SilcDList attrs = silc_attribute_payload_parse(tmp, len);
313 SILC_LOG_DEBUG(("Take client public key from attributes"));
316 silc_dlist_start(attrs);
317 while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
318 if (silc_attribute_get_attribute(attr) ==
319 SILC_ATTRIBUTE_USER_PUBLIC_KEY) {
321 if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
324 /* Take only SILC public keys */
325 if (strcmp(pk.type, "silc-rsa")) {
331 /* Verify that the server provided fingerprint matches the key */
332 silc_hash_make(server->sha1hash, pk.data, pk.data_len, f);
333 if (memcmp(f, client->data.fingerprint, sizeof(f))) {
339 /* Save the public key. */
340 if (!silc_pkcs_public_key_decode(pk.data, pk.data_len,
341 &client->data.public_key)) {
347 SILC_LOG_DEBUG(("Saved client public key from attributes"));
349 /* Add to public key hash table */
350 if (!silc_hash_table_find_by_context(server->pk_hash,
351 client->data.public_key,
353 silc_hash_table_add(server->pk_hash,
354 client->data.public_key, client);
362 silc_attribute_payload_list_free(attrs);
370 /* Handle requested attributes reply in WHOIS from client */
373 silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd)
377 SilcClientEntry client = cmd->sock->user_data;
379 /* Take Requested Attributes if set. */
380 tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
382 silc_free(client->attrs);
383 client->attrs = silc_memdup(tmp, len);
384 client->attrs_len = len;
387 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
392 /* Reiceved reply for WHOIS command. We sent the whois request to our
393 primary router, if we are normal server, and thus has now received reply
394 to the command. We will figure out what client originally sent us the
395 command and will send the reply to it. If we are router we will figure
396 out who server sent us the command and send reply to that one. */
398 SILC_SERVER_CMD_REPLY_FUNC(whois)
400 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
401 SilcStatus status, error;
403 COMMAND_CHECK_STATUS;
405 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) {
406 if (!silc_server_command_reply_whois_save(cmd))
409 if (!silc_server_command_reply_whois_save_client(cmd))
413 /* Pending callbacks are not executed if this was an list entry */
414 if (status != SILC_STATUS_OK &&
415 status != SILC_STATUS_LIST_END) {
416 silc_server_command_reply_free(cmd);
421 silc_server_command_process_error(cmd, error);
422 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
423 silc_server_command_reply_free(cmd);
427 silc_server_command_process_error(cmd, error);
428 silc_server_command_reply_free(cmd);
431 /* Caches the received WHOWAS information for a short period of time. */
434 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
436 SilcServer server = cmd->server;
437 SilcUInt32 len, id_len;
438 unsigned char *id_data;
439 char *nickname, *username, *realname, *servername = NULL;
440 SilcClientID *client_id;
441 SilcClientEntry client;
442 SilcIDCacheEntry cache = NULL;
446 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
447 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
448 username = silc_argument_get_arg_type(cmd->args, 4, &len);
449 if (!id_data || !nickname || !username)
452 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
454 client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
458 /* Check if we have this client cached already. */
460 client = silc_idlist_find_client_by_id(server->local_list, client_id,
463 client = silc_idlist_find_client_by_id(server->global_list,
464 client_id, FALSE, &cache);
469 /* If router did not find such Client ID in its lists then this must
470 be bogus client or some router in the net is buggy. */
471 if (server->server_type != SILC_SERVER)
474 /* Take hostname out of nick string if it includes it. */
475 silc_parse_userfqdn(nickname, &nick, &servername);
477 /* We don't have that client anywhere, add it. The client is added
478 to global list since server didn't have it in the lists so it must be
480 client = silc_idlist_add_client(server->global_list, nick,
481 strdup(username), strdup(realname),
482 silc_id_dup(client_id, SILC_ID_CLIENT),
483 cmd->sock->user_data, NULL,
484 SILC_ID_CACHE_EXPIRE_DEF);
486 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
490 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
491 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
492 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
493 client->servername = servername;
495 /* We have the client already, update the data */
497 /* Take hostname out of nick string if it includes it. */
498 silc_parse_userfqdn(nickname, &nick, &servername);
500 silc_free(client->nickname);
501 silc_free(client->username);
502 silc_free(client->servername);
504 client->nickname = nick;
505 client->username = strdup(username);
506 client->servername = servername;
507 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
508 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
510 /* Remove the old cache entry and create a new one */
511 silc_idcache_del_by_context(global ? server->global_list->clients :
512 server->local_list->clients, client);
513 silc_idcache_add(global ? server->global_list->clients :
514 server->local_list->clients, nick, client->id,
518 /* If client is global and is not on any channel then add that we'll
519 expire the entry after a while. */
521 silc_idlist_find_client_by_id(server->global_list, client->id,
523 if (!silc_hash_table_count(client->channels))
524 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
529 silc_free(client_id);
534 /* Received reply for WHOWAS command. Cache the client information only for
535 a short period of time. */
537 SILC_SERVER_CMD_REPLY_FUNC(whowas)
539 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
540 SilcStatus status, error;
542 COMMAND_CHECK_STATUS;
544 if (!silc_server_command_reply_whowas_save(cmd))
547 /* Pending callbacks are not executed if this was an list entry */
548 if (status != SILC_STATUS_OK &&
549 status != SILC_STATUS_LIST_END) {
550 silc_server_command_reply_free(cmd);
555 silc_server_command_process_error(cmd, error);
556 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
557 silc_server_command_reply_free(cmd);
561 silc_server_command_process_error(cmd, error);
562 silc_server_command_reply_free(cmd);
565 /* Caches the received IDENTIFY information. */
568 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
570 SilcServer server = cmd->server;
571 SilcUInt32 len, id_len;
572 unsigned char *id_data;
574 SilcClientID *client_id = NULL;
575 SilcServerID *server_id = NULL;
576 SilcChannelID *channel_id = NULL;
577 SilcClientEntry client;
578 SilcServerEntry server_entry;
579 SilcChannelEntry channel;
582 SilcIDPayload idp = NULL;
586 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
589 idp = silc_id_payload_parse(id_data, id_len);
593 name = silc_argument_get_arg_type(cmd->args, 3, &len);
594 info = silc_argument_get_arg_type(cmd->args, 4, &len);
596 id_type = silc_id_payload_get_type(idp);
600 client_id = silc_id_payload_get_id(idp);
604 SILC_LOG_DEBUG(("Received client information"));
606 client = silc_idlist_find_client_by_id(server->local_list,
607 client_id, FALSE, NULL);
609 client = silc_idlist_find_client_by_id(server->global_list, client_id,
614 /* If router did not find such Client ID in its lists then this must
615 be bogus client or some router in the net is buggy. */
616 if (server->server_type != SILC_SERVER)
621 silc_parse_userfqdn(name, &nick, NULL);
623 /* We don't have that client anywhere, add it. The client is added
624 to global list since server didn't have it in the lists so it must be
626 client = silc_idlist_add_client(server->global_list, nick,
627 info ? strdup(info) : NULL, NULL,
628 client_id, cmd->sock->user_data,
629 NULL, time(NULL) + 300);
631 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
634 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
635 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
636 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
638 /* We have the client already, update the data */
640 SILC_LOG_DEBUG(("Updating client data"));
644 silc_parse_userfqdn(name, &nick, NULL);
646 /* Remove the old cache entry */
647 silc_idcache_del_by_context(global ? server->global_list->clients :
648 server->local_list->clients, client);
650 silc_free(client->nickname);
651 client->nickname = nick;
655 silc_free(client->username);
656 client->username = strdup(info);
659 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
660 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
663 /* Add new cache entry */
664 silc_idcache_add(global ? server->global_list->clients :
665 server->local_list->clients, nick, client->id,
666 client, expire, NULL);
669 /* If client is global and is not on any channel then add that we'll
670 expire the entry after a while. */
671 if (global && server->server_type == SILC_SERVER) {
672 SilcIDCacheEntry cache = NULL;
673 silc_idlist_find_client_by_id(server->global_list, client->id,
675 if (!silc_hash_table_count(client->channels))
676 cache->expire = time(NULL) + 300;
681 silc_free(client_id);
690 server_id = silc_id_payload_get_id(idp);
694 SILC_LOG_DEBUG(("Received server information"));
696 server_entry = silc_idlist_find_server_by_id(server->local_list,
697 server_id, FALSE, NULL);
699 server_entry = silc_idlist_find_server_by_id(server->global_list,
700 server_id, FALSE, NULL);
702 /* If router did not find such Server ID in its lists then this must
703 be bogus server or some router in the net is buggy. */
704 if (server->server_type != SILC_SERVER)
707 /* We don't have that server anywhere, add it. */
708 server_entry = silc_idlist_add_server(server->global_list,
710 server_id, server->router,
711 SILC_PRIMARY_ROUTE(server));
713 silc_free(server_id);
716 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
717 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
718 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
722 silc_free(server_id);
725 case SILC_ID_CHANNEL:
729 channel_id = silc_id_payload_get_id(idp);
733 SILC_LOG_DEBUG(("Received channel information"));
735 channel = silc_idlist_find_channel_by_name(server->local_list,
738 channel = silc_idlist_find_channel_by_name(server->global_list,
741 /* If router did not find such Channel ID in its lists then this must
742 be bogus channel or some router in the net is buggy. */
743 if (server->server_type != SILC_SERVER)
746 /* We don't have that channel anywhere, add it. */
747 channel = silc_idlist_add_channel(server->global_list, strdup(name),
748 SILC_CHANNEL_MODE_NONE, channel_id,
749 server->router, NULL, NULL, 0);
751 silc_free(channel_id);
757 silc_free(channel_id);
761 silc_id_payload_free(idp);
765 silc_id_payload_free(idp);
769 /* Received reply for forwarded IDENTIFY command. We have received the
770 requested identify information now and we will cache it. After this we
771 will call the pending command so that the requestee gets the information
774 SILC_SERVER_CMD_REPLY_FUNC(identify)
776 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
777 SilcStatus status, error;
779 COMMAND_CHECK_STATUS;
781 if (!silc_server_command_reply_identify_save(cmd))
784 /* Pending callbacks are not executed if this was an list entry */
785 if (status != SILC_STATUS_OK &&
786 status != SILC_STATUS_LIST_END) {
787 silc_server_command_reply_free(cmd);
792 silc_server_command_process_error(cmd, error);
793 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
794 silc_server_command_reply_free(cmd);
798 silc_server_command_process_error(cmd, error);
799 silc_server_command_reply_free(cmd);
802 /* Received reply fro INFO command. Cache the server and its information */
804 SILC_SERVER_CMD_REPLY_FUNC(info)
806 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
807 SilcServer server = cmd->server;
808 SilcStatus status, error;
809 SilcServerEntry entry;
810 SilcServerID *server_id;
812 unsigned char *tmp, *name;
814 COMMAND_CHECK_STATUS;
817 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
820 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
825 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
829 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
832 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
835 /* Add the server to global list */
836 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
837 entry = silc_idlist_add_server(server->global_list, name, 0,
838 server_id, cmd->sock->user_data,
841 silc_free(server_id);
844 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
848 /* Get the info string */
849 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
853 entry->server_info = tmp ? strdup(tmp) : NULL;
856 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
858 silc_server_command_reply_free(cmd);
861 /* Received reply fro MOTD command. */
863 SILC_SERVER_CMD_REPLY_FUNC(motd)
865 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
866 SilcServer server = cmd->server;
867 SilcStatus status, error;
868 SilcServerEntry entry = NULL;
869 SilcServerID *server_id;
873 COMMAND_CHECK_STATUS;
876 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
879 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
883 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
886 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
891 /* If router did not find such Server ID in its lists then this must
892 be bogus client or some router in the net is buggy. */
893 if (server->server_type != SILC_SERVER)
896 /* entry isn't known so we IDENTIFY it. otherwise the
897 silc_server_command_motd won't know about it and tell
898 the client that there is no such server */
899 buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
900 ++server->cmd_ident, 5,
901 1, NULL, 0, 2, NULL, 0,
902 3, NULL, 0, 4, NULL, 0,
904 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
905 SILC_PACKET_COMMAND, 0, buffer->data,
907 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
909 silc_server_command_reply_motd,
911 silc_buffer_free(buffer);
917 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
924 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
926 silc_server_command_reply_free(cmd);
932 /* Received reply for forwarded JOIN command. Router has created or joined
933 the client to the channel. We save some channel information locally
936 SILC_SERVER_CMD_REPLY_FUNC(join)
938 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
939 SilcServer server = cmd->server;
940 SilcIDCacheEntry cache = NULL;
941 SilcStatus status, error;
943 SilcClientID *client_id = NULL;
944 SilcChannelEntry entry;
945 SilcHmac hmac = NULL;
946 SilcUInt32 id_len, len, list_count;
947 unsigned char *id_string;
948 char *channel_name, *tmp;
949 SilcUInt32 mode, created;
950 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
951 SilcPublicKey founder_key = NULL;
953 COMMAND_CHECK_STATUS;
955 /* Get channel name */
956 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
961 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
966 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
969 client_id = silc_id_payload_parse_id(tmp, len, NULL);
974 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
977 SILC_GET32_MSB(mode, tmp);
979 /* Get created boolean value */
980 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
983 SILC_GET32_MSB(created, tmp);
984 if (created != 0 && created != 1)
987 /* Get channel key */
988 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
990 keyp = silc_buffer_alloc(len);
991 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
992 silc_buffer_put(keyp, tmp, len);
995 /* Parse the Channel ID */
996 id = silc_id_payload_parse_id(id_string, id_len, NULL);
1001 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1003 if (!silc_hmac_alloc(tmp, NULL, &hmac))
1007 /* Get the list count */
1008 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1011 SILC_GET32_MSB(list_count, tmp);
1013 /* Get Client ID list */
1014 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1018 client_id_list = silc_buffer_alloc(len);
1019 silc_buffer_pull_tail(client_id_list, len);
1020 silc_buffer_put(client_id_list, tmp, len);
1022 /* Get client mode list */
1023 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1027 client_mode_list = silc_buffer_alloc(len);
1028 silc_buffer_pull_tail(client_mode_list, len);
1029 silc_buffer_put(client_mode_list, tmp, len);
1031 /* Get founder key */
1032 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1034 silc_pkcs_public_key_payload_decode(tmp, len, &founder_key);
1036 /* See whether we already have the channel. */
1037 entry = silc_idlist_find_channel_by_name(server->local_list,
1038 channel_name, &cache);
1040 /* Add new channel */
1042 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1043 (created == 0 ? "existing" : "created"), channel_name,
1044 silc_id_render(id, SILC_ID_CHANNEL)));
1046 /* If the channel is found from global list we must move it to the
1048 entry = silc_idlist_find_channel_by_name(server->global_list,
1049 channel_name, &cache);
1051 silc_idlist_del_channel(server->global_list, entry);
1053 /* Add the channel to our local list. */
1054 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1055 SILC_CHANNEL_MODE_NONE, id,
1056 server->router, NULL, hmac, 0);
1062 server->stat.my_channels++;
1063 server->stat.channels++;
1065 /* The entry exists. */
1067 /* If ID has changed, then update it to the cache too. */
1068 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
1069 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
1071 entry->disabled = FALSE;
1073 /* Remove the founder auth data if the mode is not set but we have
1074 them in the entry */
1075 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1076 silc_pkcs_public_key_free(entry->founder_key);
1077 entry->founder_key = NULL;
1082 if (entry->founder_key)
1083 silc_pkcs_public_key_free(entry->founder_key);
1084 entry->founder_key = founder_key;
1088 if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1089 silc_free(entry->hmac_name);
1090 entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1093 /* Get the ban list */
1094 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1095 if (tmp && len > 2) {
1096 SilcArgumentPayload iargs;
1098 SILC_GET16_MSB(iargc, tmp);
1099 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1101 /* Delete old ban list */
1102 if (entry->ban_list)
1103 silc_hash_table_free(entry->ban_list);
1105 silc_hash_table_alloc(0, silc_hash_ptr,
1107 silc_server_inviteban_destruct, entry, TRUE);
1109 /* Add new ban list */
1110 silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1111 silc_argument_payload_free(iargs);
1115 /* Get the invite list */
1116 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1117 if (tmp && len > 2) {
1118 SilcArgumentPayload iargs;
1120 SILC_GET16_MSB(iargc, tmp);
1121 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1123 /* Delete old invite list */
1124 if (entry->invite_list)
1125 silc_hash_table_free(entry->invite_list);
1126 entry->invite_list =
1127 silc_hash_table_alloc(0, silc_hash_ptr,
1129 silc_server_inviteban_destruct, entry, TRUE);
1131 /* Add new invite list */
1132 silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1133 silc_argument_payload_free(iargs);
1138 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1140 silc_free(entry->topic);
1141 entry->topic = strdup(tmp);
1144 /* Get channel public key list */
1145 tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1146 if (tmp && server->server_type == SILC_SERVER)
1147 silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1149 /* If channel was not created we know there is global users on the
1151 entry->global_users = (created == 0 ? TRUE : FALSE);
1153 /* If channel was just created the mask must be zero */
1154 if (!entry->global_users && mode) {
1155 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
1156 "new channel, forcing it to zero", cmd->sock->hostname));
1160 /* Save channel mode */
1163 /* Save channel key */
1165 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1166 silc_server_save_channel_key(server, keyp, entry);
1167 silc_buffer_free(keyp);
1170 /* Save the users to the channel */
1171 silc_server_save_users_on_channel(server, cmd->sock, entry,
1172 client_id, client_id_list,
1173 client_mode_list, list_count);
1174 entry->users_resolved = TRUE;
1177 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1180 silc_hmac_free(hmac);
1181 silc_free(client_id);
1182 silc_server_command_reply_free(cmd);
1184 silc_pkcs_public_key_free(founder_key);
1186 silc_buffer_free(client_id_list);
1187 if (client_mode_list)
1188 silc_buffer_free(client_mode_list);
1191 /* Received reply to STATS command. */
1193 SILC_SERVER_CMD_REPLY_FUNC(stats)
1195 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1196 SilcServer server = cmd->server;
1197 SilcStatus status, error;
1200 SilcBufferStruct buf;
1202 COMMAND_CHECK_STATUS;
1204 /* Get statistics structure */
1205 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1206 if (server->server_type != SILC_ROUTER && tmp) {
1207 silc_buffer_set(&buf, tmp, tmp_len);
1208 silc_buffer_unformat(&buf,
1209 SILC_STR_UI_INT(NULL),
1210 SILC_STR_UI_INT(NULL),
1211 SILC_STR_UI_INT(NULL),
1212 SILC_STR_UI_INT(NULL),
1213 SILC_STR_UI_INT(NULL),
1214 SILC_STR_UI_INT(NULL),
1215 SILC_STR_UI_INT(&server->stat.cell_clients),
1216 SILC_STR_UI_INT(&server->stat.cell_channels),
1217 SILC_STR_UI_INT(&server->stat.cell_servers),
1218 SILC_STR_UI_INT(&server->stat.clients),
1219 SILC_STR_UI_INT(&server->stat.channels),
1220 SILC_STR_UI_INT(&server->stat.servers),
1221 SILC_STR_UI_INT(&server->stat.routers),
1222 SILC_STR_UI_INT(&server->stat.server_ops),
1223 SILC_STR_UI_INT(&server->stat.router_ops),
1228 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1230 silc_server_command_reply_free(cmd);
1233 SILC_SERVER_CMD_REPLY_FUNC(users)
1235 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1236 SilcServer server = cmd->server;
1237 SilcStatus status, error;
1238 SilcChannelEntry channel;
1239 SilcChannelID *channel_id = NULL;
1240 SilcBuffer client_id_list;
1241 SilcBuffer client_mode_list;
1244 SilcUInt32 list_count;
1246 COMMAND_CHECK_STATUS;
1248 /* Get channel ID */
1249 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1252 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1256 /* Get channel entry */
1257 channel = silc_idlist_find_channel_by_id(server->local_list,
1260 channel = silc_idlist_find_channel_by_id(server->global_list,
1265 if (server->server_type != SILC_SERVER)
1268 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1269 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1270 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1271 1, 5, idp->data, idp->len);
1272 silc_buffer_free(idp);
1274 /* Register pending command callback. After we've received the channel
1275 information we will reprocess this command reply by re-calling this
1276 USERS command reply callback. */
1277 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1279 silc_server_command_reply_users, cmd);
1284 /* Get the list count */
1285 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1288 SILC_GET32_MSB(list_count, tmp);
1290 /* Get Client ID list */
1291 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1295 client_id_list = silc_buffer_alloc(tmp_len);
1296 silc_buffer_pull_tail(client_id_list, tmp_len);
1297 silc_buffer_put(client_id_list, tmp, tmp_len);
1299 /* Get client mode list */
1300 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1304 client_mode_list = silc_buffer_alloc(tmp_len);
1305 silc_buffer_pull_tail(client_mode_list, tmp_len);
1306 silc_buffer_put(client_mode_list, tmp, tmp_len);
1308 /* Save the users to the channel */
1309 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1310 client_id_list, client_mode_list,
1313 channel->global_users = silc_server_channel_has_global(channel);
1314 channel->users_resolved = TRUE;
1316 silc_buffer_free(client_id_list);
1317 silc_buffer_free(client_mode_list);
1320 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1321 silc_free(channel_id);
1323 silc_server_command_reply_free(cmd);
1326 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1328 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1329 SilcServer server = cmd->server;
1330 SilcStatus status, error;
1331 SilcClientEntry client = NULL;
1332 SilcServerEntry server_entry = NULL;
1333 SilcClientID *client_id = NULL;
1334 SilcServerID *server_id = NULL;
1337 SilcIDPayload idp = NULL;
1339 SilcPublicKey public_key = NULL;
1341 COMMAND_CHECK_STATUS;
1343 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1346 idp = silc_id_payload_parse(tmp, len);
1350 /* Get the public key payload */
1351 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1355 /* Decode the public key payload */
1356 if (!silc_pkcs_public_key_payload_decode(tmp, len, &public_key))
1359 id_type = silc_id_payload_get_type(idp);
1360 if (id_type == SILC_ID_CLIENT) {
1361 client_id = silc_id_payload_get_id(idp);
1363 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1366 client = silc_idlist_find_client_by_id(server->global_list,
1367 client_id, TRUE, NULL);
1372 if (!client->data.public_key) {
1373 if (!silc_hash_table_find_by_context(server->pk_hash, public_key,
1375 silc_hash_table_add(server->pk_hash, public_key, client);
1377 client->data.public_key = public_key;
1380 } else if (id_type == SILC_ID_SERVER) {
1381 server_id = silc_id_payload_get_id(idp);
1383 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1385 if (!server_entry) {
1386 server_entry = silc_idlist_find_server_by_id(server->global_list,
1387 server_id, TRUE, NULL);
1392 server_entry->data.public_key = public_key;
1399 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1401 silc_id_payload_free(idp);
1402 silc_free(client_id);
1403 silc_free(server_id);
1405 silc_pkcs_public_key_free(public_key);
1407 silc_server_command_reply_free(cmd);
1410 SILC_SERVER_CMD_REPLY_FUNC(list)
1412 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1413 SilcServer server = cmd->server;
1414 SilcStatus status, error;
1415 SilcChannelID *channel_id = NULL;
1416 SilcChannelEntry channel;
1417 SilcIDCacheEntry cache;
1419 unsigned char *tmp, *name, *topic;
1420 SilcUInt32 usercount = 0;
1421 bool global_list = FALSE;
1423 COMMAND_CHECK_STATUS;
1425 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1426 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1430 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1431 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1432 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1434 SILC_GET32_MSB(usercount, tmp);
1436 /* Add the channel entry if we do not have it already */
1437 channel = silc_idlist_find_channel_by_name(server->local_list,
1440 channel = silc_idlist_find_channel_by_name(server->global_list,
1445 /* If router did not find such channel in its lists then this must
1446 be bogus channel or some router in the net is buggy. */
1447 if (server->server_type != SILC_SERVER)
1450 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1451 SILC_CHANNEL_MODE_NONE, channel_id,
1452 server->router, NULL, NULL,
1458 /* Found, update expiry */
1459 if (global_list && server->server_type == SILC_SERVER)
1460 cache->expire = time(NULL) + 60;
1463 channel->user_count = usercount;
1466 silc_free(channel->topic);
1467 channel->topic = strdup(topic);
1470 /* Pending callbacks are not executed if this was an list entry */
1471 if (status != SILC_STATUS_OK &&
1472 status != SILC_STATUS_LIST_END) {
1473 silc_server_command_reply_free(cmd);
1477 /* Now purge all old entries from the global list, otherwise we'll might
1478 have non-existent entries for long periods of time in the cache. */
1479 silc_idcache_purge(server->global_list->channels);
1482 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1483 silc_free(channel_id);
1485 silc_server_command_reply_free(cmd);
1488 SILC_SERVER_CMD_REPLY_FUNC(watch)
1490 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1491 SilcStatus status, error;
1493 COMMAND_CHECK_STATUS;
1496 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1498 silc_server_command_reply_free(cmd);
1501 SILC_SERVER_CMD_REPLY_FUNC(ping)
1503 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1504 SilcStatus status, error;
1506 COMMAND_CHECK_STATUS;
1509 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1511 silc_server_command_reply_free(cmd);