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 /* The the user limit */
1150 tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1151 if (tmp && len == 4)
1152 SILC_GET32_MSB(entry->user_limit, tmp);
1154 /* If channel was not created we know there is global users on the
1156 entry->global_users = (created == 0 ? TRUE : FALSE);
1158 /* If channel was just created the mask must be zero */
1159 if (!entry->global_users && mode) {
1160 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
1161 "new channel, forcing it to zero", cmd->sock->hostname));
1165 /* Save channel mode */
1168 /* Save channel key */
1170 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1171 silc_server_save_channel_key(server, keyp, entry);
1172 silc_buffer_free(keyp);
1175 /* Save the users to the channel */
1176 silc_server_save_users_on_channel(server, cmd->sock, entry,
1177 client_id, client_id_list,
1178 client_mode_list, list_count);
1179 entry->users_resolved = TRUE;
1182 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1185 silc_hmac_free(hmac);
1186 silc_free(client_id);
1187 silc_server_command_reply_free(cmd);
1189 silc_pkcs_public_key_free(founder_key);
1191 silc_buffer_free(client_id_list);
1192 if (client_mode_list)
1193 silc_buffer_free(client_mode_list);
1196 /* Received reply to STATS command. */
1198 SILC_SERVER_CMD_REPLY_FUNC(stats)
1200 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1201 SilcServer server = cmd->server;
1202 SilcStatus status, error;
1205 SilcBufferStruct buf;
1207 COMMAND_CHECK_STATUS;
1209 /* Get statistics structure */
1210 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1211 if (server->server_type != SILC_ROUTER && tmp) {
1212 silc_buffer_set(&buf, tmp, tmp_len);
1213 silc_buffer_unformat(&buf,
1214 SILC_STR_UI_INT(NULL),
1215 SILC_STR_UI_INT(NULL),
1216 SILC_STR_UI_INT(NULL),
1217 SILC_STR_UI_INT(NULL),
1218 SILC_STR_UI_INT(NULL),
1219 SILC_STR_UI_INT(NULL),
1220 SILC_STR_UI_INT(&server->stat.cell_clients),
1221 SILC_STR_UI_INT(&server->stat.cell_channels),
1222 SILC_STR_UI_INT(&server->stat.cell_servers),
1223 SILC_STR_UI_INT(&server->stat.clients),
1224 SILC_STR_UI_INT(&server->stat.channels),
1225 SILC_STR_UI_INT(&server->stat.servers),
1226 SILC_STR_UI_INT(&server->stat.routers),
1227 SILC_STR_UI_INT(&server->stat.server_ops),
1228 SILC_STR_UI_INT(&server->stat.router_ops),
1233 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1235 silc_server_command_reply_free(cmd);
1238 SILC_SERVER_CMD_REPLY_FUNC(users)
1240 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1241 SilcServer server = cmd->server;
1242 SilcStatus status, error;
1243 SilcChannelEntry channel;
1244 SilcChannelID *channel_id = NULL;
1245 SilcBuffer client_id_list;
1246 SilcBuffer client_mode_list;
1249 SilcUInt32 list_count;
1251 COMMAND_CHECK_STATUS;
1253 /* Get channel ID */
1254 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1257 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1261 /* Get channel entry */
1262 channel = silc_idlist_find_channel_by_id(server->local_list,
1265 channel = silc_idlist_find_channel_by_id(server->global_list,
1270 if (server->server_type != SILC_SERVER)
1273 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1274 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1275 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1276 1, 5, idp->data, idp->len);
1277 silc_buffer_free(idp);
1279 /* Register pending command callback. After we've received the channel
1280 information we will reprocess this command reply by re-calling this
1281 USERS command reply callback. */
1282 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1284 silc_server_command_reply_users, cmd);
1289 /* Get the list count */
1290 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1293 SILC_GET32_MSB(list_count, tmp);
1295 /* Get Client ID list */
1296 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1300 client_id_list = silc_buffer_alloc(tmp_len);
1301 silc_buffer_pull_tail(client_id_list, tmp_len);
1302 silc_buffer_put(client_id_list, tmp, tmp_len);
1304 /* Get client mode list */
1305 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1309 client_mode_list = silc_buffer_alloc(tmp_len);
1310 silc_buffer_pull_tail(client_mode_list, tmp_len);
1311 silc_buffer_put(client_mode_list, tmp, tmp_len);
1313 /* Save the users to the channel */
1314 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1315 client_id_list, client_mode_list,
1318 channel->global_users = silc_server_channel_has_global(channel);
1319 channel->users_resolved = TRUE;
1321 silc_buffer_free(client_id_list);
1322 silc_buffer_free(client_mode_list);
1325 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1326 silc_free(channel_id);
1328 silc_server_command_reply_free(cmd);
1331 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1333 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1334 SilcServer server = cmd->server;
1335 SilcStatus status, error;
1336 SilcClientEntry client = NULL;
1337 SilcServerEntry server_entry = NULL;
1338 SilcClientID *client_id = NULL;
1339 SilcServerID *server_id = NULL;
1342 SilcIDPayload idp = NULL;
1344 SilcPublicKey public_key = NULL;
1346 COMMAND_CHECK_STATUS;
1348 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1351 idp = silc_id_payload_parse(tmp, len);
1355 /* Get the public key payload */
1356 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1360 /* Decode the public key payload */
1361 if (!silc_pkcs_public_key_payload_decode(tmp, len, &public_key))
1364 id_type = silc_id_payload_get_type(idp);
1365 if (id_type == SILC_ID_CLIENT) {
1366 client_id = silc_id_payload_get_id(idp);
1368 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1371 client = silc_idlist_find_client_by_id(server->global_list,
1372 client_id, TRUE, NULL);
1377 if (!client->data.public_key) {
1378 if (!silc_hash_table_find_by_context(server->pk_hash, public_key,
1380 silc_hash_table_add(server->pk_hash, public_key, client);
1382 client->data.public_key = public_key;
1385 } else if (id_type == SILC_ID_SERVER) {
1386 server_id = silc_id_payload_get_id(idp);
1388 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1390 if (!server_entry) {
1391 server_entry = silc_idlist_find_server_by_id(server->global_list,
1392 server_id, TRUE, NULL);
1397 server_entry->data.public_key = public_key;
1404 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1406 silc_id_payload_free(idp);
1407 silc_free(client_id);
1408 silc_free(server_id);
1410 silc_pkcs_public_key_free(public_key);
1412 silc_server_command_reply_free(cmd);
1415 SILC_SERVER_CMD_REPLY_FUNC(list)
1417 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1418 SilcServer server = cmd->server;
1419 SilcStatus status, error;
1420 SilcChannelID *channel_id = NULL;
1421 SilcChannelEntry channel;
1422 SilcIDCacheEntry cache;
1424 unsigned char *tmp, *name, *topic;
1425 SilcUInt32 usercount = 0;
1426 bool global_list = FALSE;
1428 COMMAND_CHECK_STATUS;
1430 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1431 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1435 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1436 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1437 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1439 SILC_GET32_MSB(usercount, tmp);
1441 /* Add the channel entry if we do not have it already */
1442 channel = silc_idlist_find_channel_by_name(server->local_list,
1445 channel = silc_idlist_find_channel_by_name(server->global_list,
1450 /* If router did not find such channel in its lists then this must
1451 be bogus channel or some router in the net is buggy. */
1452 if (server->server_type != SILC_SERVER)
1455 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1456 SILC_CHANNEL_MODE_NONE, channel_id,
1457 server->router, NULL, NULL,
1463 /* Found, update expiry */
1464 if (global_list && server->server_type == SILC_SERVER)
1465 cache->expire = time(NULL) + 60;
1468 channel->user_count = usercount;
1471 silc_free(channel->topic);
1472 channel->topic = strdup(topic);
1475 /* Pending callbacks are not executed if this was an list entry */
1476 if (status != SILC_STATUS_OK &&
1477 status != SILC_STATUS_LIST_END) {
1478 silc_server_command_reply_free(cmd);
1482 /* Now purge all old entries from the global list, otherwise we'll might
1483 have non-existent entries for long periods of time in the cache. */
1484 silc_idcache_purge(server->global_list->channels);
1487 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1488 silc_free(channel_id);
1490 silc_server_command_reply_free(cmd);
1493 SILC_SERVER_CMD_REPLY_FUNC(watch)
1495 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1496 SilcStatus status, error;
1498 COMMAND_CHECK_STATUS;
1501 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1503 silc_server_command_reply_free(cmd);
1506 SILC_SERVER_CMD_REPLY_FUNC(ping)
1508 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1509 SilcStatus status, error;
1511 COMMAND_CHECK_STATUS;
1514 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1516 silc_server_command_reply_free(cmd);