5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2003 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "serverincludes.h"
22 #include "server_internal.h"
23 #include "command_reply.h"
25 /* All functions that call the COMMAND_CHECK_STATUS macros must have
26 out: and err: goto labels. */
28 #define COMMAND_CHECK_STATUS \
30 SILC_LOG_DEBUG(("Start")); \
31 if (!silc_command_get_status(cmd->payload, &status, &error)) { \
32 if (SILC_STATUS_IS_ERROR(status)) \
34 if (status == SILC_STATUS_LIST_END) \
40 /* Server command reply list. Not all commands have reply function as
41 they are never sent by server. More maybe added later if need appears. */
42 SilcServerCommandReply silc_command_reply_list[] =
44 SILC_SERVER_CMD_REPLY(whois, WHOIS),
45 SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
46 SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
47 SILC_SERVER_CMD_REPLY(info, INFO),
48 SILC_SERVER_CMD_REPLY(motd, MOTD),
49 SILC_SERVER_CMD_REPLY(join, JOIN),
50 SILC_SERVER_CMD_REPLY(stats, STATS),
51 SILC_SERVER_CMD_REPLY(users, USERS),
52 SILC_SERVER_CMD_REPLY(getkey, GETKEY),
53 SILC_SERVER_CMD_REPLY(list, LIST),
54 SILC_SERVER_CMD_REPLY(watch, WATCH),
55 SILC_SERVER_CMD_REPLY(ping, PING),
60 /* Process received command reply. */
62 void silc_server_command_reply_process(SilcServer server,
63 SilcSocketConnection sock,
66 SilcServerCommandReply *cmd;
67 SilcServerCommandReplyContext ctx;
68 SilcCommandPayload payload;
71 SILC_LOG_DEBUG(("Start"));
73 /* Get command reply payload from packet */
74 payload = silc_command_payload_parse(buffer->data, buffer->len);
76 /* Silently ignore bad reply packet */
77 SILC_LOG_DEBUG(("Bad command reply packet"));
81 /* Allocate command reply context. This must be free'd by the
82 command reply routine receiving it. */
83 ctx = silc_calloc(1, sizeof(*ctx));
85 ctx->sock = silc_socket_dup(sock);
86 ctx->payload = payload;
87 ctx->args = silc_command_get_args(ctx->payload);
88 ctx->ident = silc_command_get_ident(ctx->payload);
89 command = silc_command_get(ctx->payload);
91 /* Client is not allowed to send reply to all commands */
92 if (sock->type == SILC_SOCKET_TYPE_CLIENT &&
93 command != SILC_COMMAND_WHOIS) {
94 silc_server_command_reply_free(ctx);
98 /* Check for pending commands and mark to be exeucted */
100 silc_server_command_pending_check(server, command,
101 ctx->ident, &ctx->callbacks_count);
103 /* Execute command reply */
104 for (cmd = silc_command_reply_list; cmd->cb; cmd++)
105 if (cmd->cmd == command)
108 if (cmd == NULL || !cmd->cb) {
109 silc_server_command_reply_free(ctx);
116 /* Free command reply context and its internals. */
118 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
121 silc_command_payload_free(cmd->payload);
123 silc_socket_free(cmd->sock); /* Decrease the reference counter */
124 silc_free(cmd->callbacks);
130 silc_server_command_process_error(SilcServerCommandReplyContext cmd,
133 SilcServer server = cmd->server;
135 /* If we received notify for invalid ID we'll remove the ID if we
137 if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
138 cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
139 SilcClientEntry client;
141 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
143 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
145 SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
146 "the entry from cache"));
147 client = silc_idlist_find_client_by_id(server->global_list,
148 client_id, FALSE, NULL);
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,
889 /* entry isn't known so we IDENTIFY it. otherwise the
890 * silc_server_command_motd won't know about it and tell
891 * the client that there is no such server */
893 buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
894 ++server->cmd_ident, 5,
895 1, NULL, 0, 2, NULL, 0,
896 3, NULL, 0, 4, NULL, 0,
898 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
899 SILC_PACKET_COMMAND, 0, buffer->data,
901 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
903 silc_server_command_reply_motd,
905 silc_buffer_free(buffer);
911 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
918 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
920 silc_server_command_reply_free(cmd);
926 /* Received reply for forwarded JOIN command. Router has created or joined
927 the client to the channel. We save some channel information locally
930 SILC_SERVER_CMD_REPLY_FUNC(join)
932 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
933 SilcServer server = cmd->server;
934 SilcIDCacheEntry cache = NULL;
935 SilcStatus status, error;
937 SilcClientID *client_id = NULL;
938 SilcChannelEntry entry;
939 SilcHmac hmac = NULL;
940 SilcUInt32 id_len, len, list_count;
941 unsigned char *id_string;
942 char *channel_name, *tmp;
943 SilcUInt32 mode, created;
944 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
945 SilcPublicKey founder_key = NULL;
947 COMMAND_CHECK_STATUS;
949 /* Get channel name */
950 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
955 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
960 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
963 client_id = silc_id_payload_parse_id(tmp, len, NULL);
968 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
971 SILC_GET32_MSB(mode, tmp);
973 /* Get created boolean value */
974 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
977 SILC_GET32_MSB(created, tmp);
978 if (created != 0 && created != 1)
981 /* Get channel key */
982 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
984 keyp = silc_buffer_alloc(len);
985 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
986 silc_buffer_put(keyp, tmp, len);
989 /* Parse the Channel ID */
990 id = silc_id_payload_parse_id(id_string, id_len, NULL);
995 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
997 if (!silc_hmac_alloc(tmp, NULL, &hmac))
1001 /* Get the list count */
1002 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1005 SILC_GET32_MSB(list_count, tmp);
1007 /* Get Client ID list */
1008 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1012 client_id_list = silc_buffer_alloc(len);
1013 silc_buffer_pull_tail(client_id_list, len);
1014 silc_buffer_put(client_id_list, tmp, len);
1016 /* Get client mode list */
1017 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1021 client_mode_list = silc_buffer_alloc(len);
1022 silc_buffer_pull_tail(client_mode_list, len);
1023 silc_buffer_put(client_mode_list, tmp, len);
1025 /* Get founder key */
1026 tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1028 silc_pkcs_public_key_payload_decode(tmp, len, &founder_key);
1030 /* See whether we already have the channel. */
1031 entry = silc_idlist_find_channel_by_name(server->local_list,
1032 channel_name, &cache);
1034 /* Add new channel */
1036 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1037 (created == 0 ? "existing" : "created"), channel_name,
1038 silc_id_render(id, SILC_ID_CHANNEL)));
1040 /* If the channel is found from global list we must move it to the
1042 entry = silc_idlist_find_channel_by_name(server->global_list,
1043 channel_name, &cache);
1045 silc_idlist_del_channel(server->global_list, entry);
1047 /* Add the channel to our local list. */
1048 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1049 SILC_CHANNEL_MODE_NONE, id,
1050 server->router, NULL, hmac, 0);
1056 server->stat.my_channels++;
1057 server->stat.channels++;
1059 /* The entry exists. */
1061 /* If ID has changed, then update it to the cache too. */
1062 if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
1063 silc_idlist_replace_channel_id(server->local_list, entry->id, id);
1065 entry->disabled = FALSE;
1067 /* Remove the founder auth data if the mode is not set but we have
1068 them in the entry */
1069 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1070 silc_pkcs_public_key_free(entry->founder_key);
1071 entry->founder_key = NULL;
1076 if (entry->founder_key)
1077 silc_pkcs_public_key_free(entry->founder_key);
1078 entry->founder_key = founder_key;
1082 if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1083 silc_free(entry->hmac_name);
1084 entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1087 /* Get the ban list */
1088 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1089 if (tmp && len > 2) {
1090 SilcArgumentPayload iargs;
1092 SILC_GET16_MSB(iargc, tmp);
1093 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1095 /* Delete old ban list */
1096 if (entry->ban_list)
1097 silc_hash_table_free(entry->ban_list);
1099 silc_hash_table_alloc(0, silc_hash_ptr,
1101 silc_server_inviteban_destruct, entry, TRUE);
1103 /* Add new ban list */
1104 silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1105 silc_argument_payload_free(iargs);
1109 /* Get the invite list */
1110 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1111 if (tmp && len > 2) {
1112 SilcArgumentPayload iargs;
1114 SILC_GET16_MSB(iargc, tmp);
1115 iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1117 /* Delete old invite list */
1118 if (entry->invite_list)
1119 silc_hash_table_free(entry->invite_list);
1120 entry->invite_list =
1121 silc_hash_table_alloc(0, silc_hash_ptr,
1123 silc_server_inviteban_destruct, entry, TRUE);
1125 /* Add new invite list */
1126 silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1127 silc_argument_payload_free(iargs);
1132 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1134 silc_free(entry->topic);
1135 entry->topic = strdup(tmp);
1138 /* Get channel public key list */
1139 tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1140 if (tmp && server->server_type == SILC_SERVER)
1141 silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1143 /* If channel was not created we know there is global users on the
1145 entry->global_users = (created == 0 ? TRUE : FALSE);
1147 /* If channel was just created the mask must be zero */
1148 if (!entry->global_users && mode) {
1149 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
1150 "new channel, forcing it to zero", cmd->sock->hostname));
1154 /* Save channel mode */
1157 /* Save channel key */
1159 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1160 silc_server_save_channel_key(server, keyp, entry);
1161 silc_buffer_free(keyp);
1164 /* Save the users to the channel */
1165 silc_server_save_users_on_channel(server, cmd->sock, entry,
1166 client_id, client_id_list,
1167 client_mode_list, list_count);
1168 entry->users_resolved = TRUE;
1171 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1174 silc_hmac_free(hmac);
1175 silc_free(client_id);
1176 silc_server_command_reply_free(cmd);
1178 silc_pkcs_public_key_free(founder_key);
1180 silc_buffer_free(client_id_list);
1181 if (client_mode_list)
1182 silc_buffer_free(client_mode_list);
1185 /* Received reply to STATS command. */
1187 SILC_SERVER_CMD_REPLY_FUNC(stats)
1189 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1190 SilcServer server = cmd->server;
1191 SilcStatus status, error;
1194 SilcBufferStruct buf;
1196 COMMAND_CHECK_STATUS;
1198 /* Get statistics structure */
1199 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1200 if (server->server_type != SILC_ROUTER && tmp) {
1201 silc_buffer_set(&buf, tmp, tmp_len);
1202 silc_buffer_unformat(&buf,
1203 SILC_STR_UI_INT(NULL),
1204 SILC_STR_UI_INT(NULL),
1205 SILC_STR_UI_INT(NULL),
1206 SILC_STR_UI_INT(NULL),
1207 SILC_STR_UI_INT(NULL),
1208 SILC_STR_UI_INT(NULL),
1209 SILC_STR_UI_INT(&server->stat.cell_clients),
1210 SILC_STR_UI_INT(&server->stat.cell_channels),
1211 SILC_STR_UI_INT(&server->stat.cell_servers),
1212 SILC_STR_UI_INT(&server->stat.clients),
1213 SILC_STR_UI_INT(&server->stat.channels),
1214 SILC_STR_UI_INT(&server->stat.servers),
1215 SILC_STR_UI_INT(&server->stat.routers),
1216 SILC_STR_UI_INT(&server->stat.server_ops),
1217 SILC_STR_UI_INT(&server->stat.router_ops),
1222 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1224 silc_server_command_reply_free(cmd);
1227 SILC_SERVER_CMD_REPLY_FUNC(users)
1229 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1230 SilcServer server = cmd->server;
1231 SilcStatus status, error;
1232 SilcChannelEntry channel;
1233 SilcChannelID *channel_id = NULL;
1234 SilcBuffer client_id_list;
1235 SilcBuffer client_mode_list;
1238 SilcUInt32 list_count;
1240 COMMAND_CHECK_STATUS;
1242 /* Get channel ID */
1243 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1246 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1250 /* Get channel entry */
1251 channel = silc_idlist_find_channel_by_id(server->local_list,
1254 channel = silc_idlist_find_channel_by_id(server->global_list,
1259 if (server->server_type != SILC_SERVER)
1262 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1263 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1264 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1265 1, 5, idp->data, idp->len);
1266 silc_buffer_free(idp);
1268 /* Register pending command callback. After we've received the channel
1269 information we will reprocess this command reply by re-calling this
1270 USERS command reply callback. */
1271 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1273 silc_server_command_reply_users, cmd);
1278 /* Get the list count */
1279 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1282 SILC_GET32_MSB(list_count, tmp);
1284 /* Get Client ID list */
1285 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1289 client_id_list = silc_buffer_alloc(tmp_len);
1290 silc_buffer_pull_tail(client_id_list, tmp_len);
1291 silc_buffer_put(client_id_list, tmp, tmp_len);
1293 /* Get client mode list */
1294 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1298 client_mode_list = silc_buffer_alloc(tmp_len);
1299 silc_buffer_pull_tail(client_mode_list, tmp_len);
1300 silc_buffer_put(client_mode_list, tmp, tmp_len);
1302 /* Save the users to the channel */
1303 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1304 client_id_list, client_mode_list,
1307 channel->global_users = silc_server_channel_has_global(channel);
1308 channel->users_resolved = TRUE;
1310 silc_buffer_free(client_id_list);
1311 silc_buffer_free(client_mode_list);
1314 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1315 silc_free(channel_id);
1317 silc_server_command_reply_free(cmd);
1320 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1322 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1323 SilcServer server = cmd->server;
1324 SilcStatus status, error;
1325 SilcClientEntry client = NULL;
1326 SilcServerEntry server_entry = NULL;
1327 SilcClientID *client_id = NULL;
1328 SilcServerID *server_id = NULL;
1331 SilcIDPayload idp = NULL;
1333 SilcPublicKey public_key = NULL;
1335 COMMAND_CHECK_STATUS;
1337 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1340 idp = silc_id_payload_parse(tmp, len);
1344 /* Get the public key payload */
1345 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1349 /* Decode the public key payload */
1350 if (!silc_pkcs_public_key_payload_decode(tmp, len, &public_key))
1353 id_type = silc_id_payload_get_type(idp);
1354 if (id_type == SILC_ID_CLIENT) {
1355 client_id = silc_id_payload_get_id(idp);
1357 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1360 client = silc_idlist_find_client_by_id(server->global_list,
1361 client_id, TRUE, NULL);
1366 if (!silc_hash_table_find_by_context(server->pk_hash, public_key,
1368 silc_hash_table_add(server->pk_hash, public_key, client);
1370 client->data.public_key = public_key;
1372 } else if (id_type == SILC_ID_SERVER) {
1373 server_id = silc_id_payload_get_id(idp);
1375 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1377 if (!server_entry) {
1378 server_entry = silc_idlist_find_server_by_id(server->global_list,
1379 server_id, TRUE, NULL);
1384 server_entry->data.public_key = public_key;
1391 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1393 silc_id_payload_free(idp);
1394 silc_free(client_id);
1395 silc_free(server_id);
1397 silc_pkcs_public_key_free(public_key);
1399 silc_server_command_reply_free(cmd);
1402 SILC_SERVER_CMD_REPLY_FUNC(list)
1404 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1405 SilcServer server = cmd->server;
1406 SilcStatus status, error;
1407 SilcChannelID *channel_id = NULL;
1408 SilcChannelEntry channel;
1409 SilcIDCacheEntry cache;
1411 unsigned char *tmp, *name, *topic;
1412 SilcUInt32 usercount = 0;
1413 bool global_list = FALSE;
1415 COMMAND_CHECK_STATUS;
1417 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1418 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1422 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1423 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1424 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1426 SILC_GET32_MSB(usercount, tmp);
1428 /* Add the channel entry if we do not have it already */
1429 channel = silc_idlist_find_channel_by_name(server->local_list,
1432 channel = silc_idlist_find_channel_by_name(server->global_list,
1437 /* If router did not find such channel in its lists then this must
1438 be bogus channel or some router in the net is buggy. */
1439 if (server->server_type != SILC_SERVER)
1442 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1443 SILC_CHANNEL_MODE_NONE, channel_id,
1444 server->router, NULL, NULL,
1450 /* Found, update expiry */
1451 if (global_list && server->server_type == SILC_SERVER)
1452 cache->expire = time(NULL) + 60;
1455 channel->user_count = usercount;
1458 silc_free(channel->topic);
1459 channel->topic = strdup(topic);
1462 /* Pending callbacks are not executed if this was an list entry */
1463 if (status != SILC_STATUS_OK &&
1464 status != SILC_STATUS_LIST_END) {
1465 silc_server_command_reply_free(cmd);
1469 /* Now purge all old entries from the global list, otherwise we'll might
1470 have non-existent entries for long periods of time in the cache. */
1471 silc_idcache_purge(server->global_list->channels);
1474 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1475 silc_free(channel_id);
1477 silc_server_command_reply_free(cmd);
1480 SILC_SERVER_CMD_REPLY_FUNC(watch)
1482 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1483 SilcStatus status, error;
1485 COMMAND_CHECK_STATUS;
1488 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1490 silc_server_command_reply_free(cmd);
1493 SILC_SERVER_CMD_REPLY_FUNC(ping)
1495 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1496 SilcStatus status, error;
1498 COMMAND_CHECK_STATUS;
1501 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1503 silc_server_command_reply_free(cmd);