5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
24 #include "command_reply.h"
26 /* All functions that call the COMMAND_CHECK_STATUS or the
27 COMMAND_CHECK_STATUS_LIST macros must have out: goto label. */
29 #define COMMAND_CHECK_STATUS \
31 SILC_LOG_DEBUG(("Start")); \
32 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); \
33 if (status != SILC_STATUS_OK) \
37 #define COMMAND_CHECK_STATUS_LIST \
39 SILC_LOG_DEBUG(("Start")); \
40 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); \
41 if (status != SILC_STATUS_OK && \
42 status != SILC_STATUS_LIST_START && \
43 status != SILC_STATUS_LIST_ITEM && \
44 status != SILC_STATUS_LIST_END) \
48 /* Server command reply list. Not all commands have reply function as
49 they are never sent by server. More maybe added later if need appears. */
50 SilcServerCommandReply silc_command_reply_list[] =
52 SILC_SERVER_CMD_REPLY(whois, WHOIS),
53 SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
54 SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
55 SILC_SERVER_CMD_REPLY(info, INFO),
56 SILC_SERVER_CMD_REPLY(motd, MOTD),
57 SILC_SERVER_CMD_REPLY(join, JOIN),
58 SILC_SERVER_CMD_REPLY(users, USERS),
59 SILC_SERVER_CMD_REPLY(getkey, GETKEY),
60 SILC_SERVER_CMD_REPLY(list, LIST),
65 /* Process received command reply. */
67 void silc_server_command_reply_process(SilcServer server,
68 SilcSocketConnection sock,
71 SilcServerCommandReply *cmd;
72 SilcServerCommandReplyContext ctx;
73 SilcCommandPayload payload;
77 SILC_LOG_DEBUG(("Start"));
79 /* Get command reply payload from packet */
80 payload = silc_command_payload_parse(buffer);
82 /* Silently ignore bad reply packet */
83 SILC_LOG_DEBUG(("Bad command reply packet"));
87 /* Allocate command reply context. This must be free'd by the
88 command reply routine receiving it. */
89 ctx = silc_calloc(1, sizeof(*ctx));
91 ctx->sock = silc_socket_dup(sock);
92 ctx->payload = payload;
93 ctx->args = silc_command_get_args(ctx->payload);
94 ident = silc_command_get_ident(ctx->payload);
96 /* Check for pending commands and mark to be exeucted */
98 silc_server_command_pending_check(server, ctx,
99 silc_command_get(ctx->payload),
100 ident, &ctx->callbacks_count);
102 /* Execute command reply */
103 command = silc_command_get(ctx->payload);
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);
129 /* Caches the received WHOIS information. */
132 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
134 SilcServer server = cmd->server;
135 unsigned char *tmp, *id_data;
136 char *nickname, *username, *realname, *servername = NULL;
137 unsigned char *fingerprint;
138 SilcClientID *client_id;
139 SilcClientEntry client;
142 uint32 mode = 0, len, id_len, flen;
144 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
145 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
146 username = silc_argument_get_arg_type(cmd->args, 4, &len);
147 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
148 if (!id_data || !nickname || !username || !realname) {
149 SILC_LOG_ERROR(("Incomplete WHOIS info: %s %s %s",
150 nickname ? nickname : "",
151 username ? username : "",
152 realname ? realname : ""));
156 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
158 SILC_GET32_MSB(mode, tmp);
160 client_id = silc_id_payload_parse_id(id_data, id_len);
164 fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
166 /* Check if we have this client cached already. */
168 client = silc_idlist_find_client_by_id(server->local_list, client_id,
171 client = silc_idlist_find_client_by_id(server->global_list, client_id,
177 /* If router did not find such Client ID in its lists then this must
178 be bogus client or some router in the net is buggy. */
179 if (server->server_type != SILC_SERVER)
182 /* Take hostname out of nick string if it includes it. */
183 silc_parse_userfqdn(nickname, &nick, &servername);
185 /* We don't have that client anywhere, add it. The client is added
186 to global list since server didn't have it in the lists so it must be
188 client = silc_idlist_add_client(server->global_list, nick,
190 strdup(realname), client_id,
191 cmd->sock->user_data, NULL);
193 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
197 client->data.status |=
198 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
199 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
201 client->servername = servername;
203 /* We have the client already, update the data */
205 SILC_LOG_DEBUG(("Updating client data"));
207 /* Take hostname out of nick string if it includes it. */
208 silc_parse_userfqdn(nickname, &nick, &servername);
210 /* Remove the old cache entry */
211 silc_idcache_del_by_context(global ? server->global_list->clients :
212 server->local_list->clients, client);
214 silc_free(client->nickname);
215 silc_free(client->username);
216 silc_free(client->userinfo);
217 silc_free(client->servername);
219 client->nickname = nick;
220 client->username = strdup(username);
221 client->userinfo = strdup(realname);
222 client->servername = servername;
224 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
225 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
227 /* Create new cache entry */
228 silc_idcache_add(global ? server->global_list->clients :
229 server->local_list->clients, nick, client->id,
231 silc_free(client_id);
234 if (fingerprint && flen == sizeof(client->data.fingerprint))
235 memcpy(client->data.fingerprint, fingerprint, flen);
240 /* Reiceved reply for WHOIS command. We sent the whois request to our
241 primary router, if we are normal server, and thus has now received reply
242 to the command. We will figure out what client originally sent us the
243 command and will send the reply to it. If we are router we will figure
244 out who server sent us the command and send reply to that one. */
246 SILC_SERVER_CMD_REPLY_FUNC(whois)
248 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
249 SilcCommandStatus status;
251 COMMAND_CHECK_STATUS_LIST;
253 if (!silc_server_command_reply_whois_save(cmd))
256 /* Pending callbacks are not executed if this was an list entry */
257 if (status != SILC_STATUS_OK &&
258 status != SILC_STATUS_LIST_END) {
259 silc_server_command_reply_free(cmd);
264 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
265 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS);
266 silc_server_command_reply_free(cmd);
269 /* Caches the received WHOWAS information for a short period of time. */
272 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
274 SilcServer server = cmd->server;
276 unsigned char *id_data;
277 char *nickname, *username, *realname, *servername = NULL;
278 SilcClientID *client_id;
279 SilcClientEntry client;
280 SilcIDCacheEntry cache = NULL;
284 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
285 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
286 username = silc_argument_get_arg_type(cmd->args, 4, &len);
287 if (!id_data || !nickname || !username)
290 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
292 client_id = silc_id_payload_parse_id(id_data, id_len);
296 /* Check if we have this client cached already. */
298 client = silc_idlist_find_client_by_id(server->local_list, client_id,
301 client = silc_idlist_find_client_by_id(server->global_list,
302 client_id, FALSE, &cache);
307 /* If router did not find such Client ID in its lists then this must
308 be bogus client or some router in the net is buggy. */
309 if (server->server_type != SILC_SERVER)
312 /* Take hostname out of nick string if it includes it. */
313 silc_parse_userfqdn(nickname, &nick, &servername);
315 /* We don't have that client anywhere, add it. The client is added
316 to global list since server didn't have it in the lists so it must be
318 client = silc_idlist_add_client(server->global_list, nick,
319 strdup(username), strdup(realname),
320 silc_id_dup(client_id, SILC_ID_CLIENT),
321 cmd->sock->user_data, NULL);
323 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
327 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
328 client = silc_idlist_find_client_by_id(server->global_list,
329 client_id, TRUE, &cache);
330 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
331 client->servername = servername;
333 /* We have the client already, update the data */
335 /* Take hostname out of nick string if it includes it. */
336 silc_parse_userfqdn(nickname, &nick, &servername);
338 silc_free(client->nickname);
339 silc_free(client->username);
341 client->nickname = nick;
342 client->username = strdup(username);
343 client->servername = servername;
345 /* Remove the old cache entry and create a new one */
346 silc_idcache_del_by_context(global ? server->global_list->clients :
347 server->local_list->clients, client);
348 silc_idcache_add(global ? server->global_list->clients :
349 server->local_list->clients, nick, client->id,
353 silc_free(client_id);
358 /* Received reply for WHOWAS command. Cache the client information only for
359 a short period of time. */
361 SILC_SERVER_CMD_REPLY_FUNC(whowas)
363 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
364 SilcCommandStatus status;
366 COMMAND_CHECK_STATUS_LIST;
368 if (!silc_server_command_reply_whowas_save(cmd))
371 /* Pending callbacks are not executed if this was an list entry */
372 if (status != SILC_STATUS_OK &&
373 status != SILC_STATUS_LIST_END) {
374 silc_server_command_reply_free(cmd);
379 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
380 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOWAS);
381 silc_server_command_reply_free(cmd);
384 /* Caches the received IDENTIFY information. */
387 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
389 SilcServer server = cmd->server;
391 unsigned char *id_data;
393 SilcClientID *client_id = NULL;
394 SilcServerID *server_id = NULL;
395 SilcChannelID *channel_id = NULL;
396 SilcClientEntry client;
397 SilcServerEntry server_entry;
398 SilcChannelEntry channel;
401 SilcIDPayload idp = NULL;
404 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
407 idp = silc_id_payload_parse_data(id_data, id_len);
411 name = silc_argument_get_arg_type(cmd->args, 3, &len);
412 info = silc_argument_get_arg_type(cmd->args, 4, &len);
414 id_type = silc_id_payload_get_type(idp);
418 client_id = silc_id_payload_get_id(idp);
422 SILC_LOG_DEBUG(("Received client information"));
424 client = silc_idlist_find_client_by_id(server->local_list,
425 client_id, FALSE, NULL);
427 client = silc_idlist_find_client_by_id(server->global_list, client_id,
432 /* If router did not find such Client ID in its lists then this must
433 be bogus client or some router in the net is buggy. */
434 if (server->server_type != SILC_SERVER)
439 silc_parse_userfqdn(name, &nick, NULL);
441 /* We don't have that client anywhere, add it. The client is added
442 to global list since server didn't have it in the lists so it must be
444 client = silc_idlist_add_client(server->global_list, nick,
445 info ? strdup(info) : NULL, NULL,
446 client_id, cmd->sock->user_data, NULL);
448 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
451 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
452 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
453 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
455 /* We have the client already, update the data */
457 SILC_LOG_DEBUG(("Updating client data"));
461 silc_parse_userfqdn(name, &nick, NULL);
463 /* Remove the old cache entry */
464 silc_idcache_del_by_context(global ? server->global_list->clients :
465 server->local_list->clients, client);
467 silc_free(client->nickname);
468 client->nickname = nick;
472 silc_free(client->username);
473 client->username = strdup(info);
476 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
477 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
480 /* Add new cache entry */
481 silc_idcache_add(global ? server->global_list->clients :
482 server->local_list->clients, nick, client->id,
486 silc_free(client_id);
492 server_id = silc_id_payload_get_id(idp);
496 SILC_LOG_DEBUG(("Received server information"));
498 server_entry = silc_idlist_find_server_by_id(server->local_list,
499 server_id, FALSE, NULL);
501 server_entry = silc_idlist_find_server_by_id(server->global_list,
502 server_id, FALSE, NULL);
504 /* If router did not find such Server ID in its lists then this must
505 be bogus server or some router in the net is buggy. */
506 if (server->server_type != SILC_SERVER)
509 /* We don't have that server anywhere, add it. */
510 server_entry = silc_idlist_add_server(server->global_list,
512 server_id, NULL, NULL);
514 silc_free(server_id);
517 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
518 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
519 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
523 silc_free(server_id);
526 case SILC_ID_CHANNEL:
527 channel_id = silc_id_payload_get_id(idp);
531 SILC_LOG_DEBUG(("Received channel information"));
533 channel = silc_idlist_find_channel_by_id(server->local_list,
536 channel = silc_idlist_find_channel_by_id(server->global_list, channel_id,
539 /* If router did not find such Channel ID in its lists then this must
540 be bogus channel or some router in the net is buggy. */
541 if (server->server_type != SILC_SERVER)
544 /* We don't have that server anywhere, add it. */
545 channel = silc_idlist_add_channel(server->global_list, strdup(name),
546 SILC_CHANNEL_MODE_NONE, channel_id,
550 silc_free(channel_id);
556 silc_free(channel_id);
560 silc_id_payload_free(idp);
564 silc_id_payload_free(idp);
568 /* Received reply for forwarded IDENTIFY command. We have received the
569 requested identify information now and we will cache it. After this we
570 will call the pending command so that the requestee gets the information
573 SILC_SERVER_CMD_REPLY_FUNC(identify)
575 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
576 SilcCommandStatus status;
578 COMMAND_CHECK_STATUS_LIST;
580 if (!silc_server_command_reply_identify_save(cmd))
583 /* Pending callbacks are not executed if this was an list entry */
584 if (status != SILC_STATUS_OK &&
585 status != SILC_STATUS_LIST_END) {
586 silc_server_command_reply_free(cmd);
591 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
592 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_IDENTIFY);
593 silc_server_command_reply_free(cmd);
596 /* Received reply fro INFO command. Cache the server and its information */
598 SILC_SERVER_CMD_REPLY_FUNC(info)
600 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
601 SilcServer server = cmd->server;
602 SilcCommandStatus status;
603 SilcServerEntry entry;
604 SilcServerID *server_id;
606 unsigned char *tmp, *name;
608 COMMAND_CHECK_STATUS;
611 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
614 server_id = silc_id_payload_parse_id(tmp, tmp_len);
619 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
623 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
626 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
629 /* Add the server to global list */
630 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
631 entry = silc_idlist_add_server(server->global_list, name, 0,
632 server_id, NULL, NULL);
634 silc_free(server_id);
637 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
641 /* Get the info string */
642 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
646 entry->server_info = tmp ? strdup(tmp) : NULL;
649 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
650 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO);
651 silc_server_command_reply_free(cmd);
654 /* Received reply fro MOTD command. */
656 SILC_SERVER_CMD_REPLY_FUNC(motd)
658 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
659 SilcServer server = cmd->server;
660 SilcCommandStatus status;
661 SilcServerEntry entry = NULL;
662 SilcServerID *server_id;
666 COMMAND_CHECK_STATUS;
669 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
672 server_id = silc_id_payload_parse_id(tmp, tmp_len);
676 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
679 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
686 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
693 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
694 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_MOTD);
695 silc_server_command_reply_free(cmd);
701 /* Received reply for forwarded JOIN command. Router has created or joined
702 the client to the channel. We save some channel information locally
705 SILC_SERVER_CMD_REPLY_FUNC(join)
707 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
708 SilcServer server = cmd->server;
709 SilcIDCacheEntry cache = NULL;
710 SilcCommandStatus status;
712 SilcClientID *client_id = NULL;
713 SilcChannelEntry entry;
714 SilcHmac hmac = NULL;
715 uint32 id_len, len, list_count;
716 unsigned char *id_string;
717 char *channel_name, *tmp;
718 uint32 mode, created;
719 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
721 COMMAND_CHECK_STATUS;
723 /* Get channel name */
724 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
729 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
734 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
737 client_id = silc_id_payload_parse_id(tmp, len);
742 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
745 SILC_GET32_MSB(mode, tmp);
747 /* Get created boolean value */
748 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
751 SILC_GET32_MSB(created, tmp);
752 if (created != 0 && created != 1)
755 /* Get channel key */
756 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
758 keyp = silc_buffer_alloc(len);
759 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
760 silc_buffer_put(keyp, tmp, len);
763 id = silc_id_payload_parse_id(id_string, id_len);
768 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
770 if (!silc_hmac_alloc(tmp, NULL, &hmac))
774 /* Get the list count */
775 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
778 SILC_GET32_MSB(list_count, tmp);
780 /* Get Client ID list */
781 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
785 client_id_list = silc_buffer_alloc(len);
786 silc_buffer_pull_tail(client_id_list, len);
787 silc_buffer_put(client_id_list, tmp, len);
789 /* Get client mode list */
790 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
794 client_mode_list = silc_buffer_alloc(len);
795 silc_buffer_pull_tail(client_mode_list, len);
796 silc_buffer_put(client_mode_list, tmp, len);
798 /* See whether we already have the channel. */
799 entry = silc_idlist_find_channel_by_name(server->local_list,
800 channel_name, &cache);
802 /* Add new channel */
804 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
805 (created == 0 ? "existing" : "created"), channel_name,
806 silc_id_render(id, SILC_ID_CHANNEL)));
808 /* If the channel is found from global list we must move it to the
810 entry = silc_idlist_find_channel_by_name(server->global_list,
811 channel_name, &cache);
813 silc_idlist_del_channel(server->global_list, entry);
815 /* Add the channel to our local list. */
816 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
817 SILC_CHANNEL_MODE_NONE, id,
818 server->router, NULL, hmac);
823 server->stat.my_channels++;
825 /* The entry exists. */
826 silc_free(cache->id);
828 cache->id = entry->id;
829 entry->disabled = FALSE;
831 /* Remove the founder auth data if the mode is not set but we have
833 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
834 silc_pkcs_public_key_free(entry->founder_key);
835 if (entry->founder_passwd) {
836 silc_free(entry->founder_passwd);
837 entry->founder_passwd = NULL;
842 if (entry->hmac_name && hmac) {
843 silc_free(entry->hmac_name);
844 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
847 /* Get the ban list */
848 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
851 silc_free(entry->ban_list);
852 entry->ban_list = silc_calloc(len, sizeof(*entry->ban_list));
853 memcpy(entry->ban_list, tmp, len);
856 /* Get the invite list */
857 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
859 if (entry->invite_list)
860 silc_free(entry->invite_list);
861 entry->invite_list = silc_calloc(len, sizeof(*entry->invite_list));
862 memcpy(entry->invite_list, tmp, len);
866 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
869 silc_free(entry->topic);
870 entry->topic = strdup(tmp);
873 /* If channel was not created we know there is global users on the
875 entry->global_users = (created == 0 ? TRUE : FALSE);
877 /* If channel was just created the mask must be zero */
878 if (!entry->global_users && mode) {
879 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
880 "new channel, forcing it to zero", cmd->sock->hostname));
884 /* Save channel mode */
887 /* Save channel key */
888 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
889 silc_server_save_channel_key(server, keyp, entry);
891 silc_buffer_free(keyp);
893 /* Save the users to the channel */
894 silc_server_save_users_on_channel(server, cmd->sock, entry,
895 client_id, client_id_list,
896 client_mode_list, list_count);
899 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
900 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_JOIN);
901 silc_free(client_id);
902 silc_server_command_reply_free(cmd);
905 silc_buffer_free(client_id_list);
906 if (client_mode_list)
907 silc_buffer_free(client_mode_list);
910 SILC_SERVER_CMD_REPLY_FUNC(users)
912 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
913 SilcServer server = cmd->server;
914 SilcCommandStatus status;
915 SilcChannelEntry channel;
916 SilcChannelID *channel_id = NULL;
917 SilcBuffer client_id_list;
918 SilcBuffer client_mode_list;
923 COMMAND_CHECK_STATUS;
926 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
929 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
933 /* Get channel entry */
934 channel = silc_idlist_find_channel_by_id(server->local_list,
937 channel = silc_idlist_find_channel_by_id(server->global_list,
942 if (server->server_type != SILC_SERVER)
945 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
946 silc_server_send_command(server, server->router->connection,
947 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
948 1, 5, idp->data, idp->len);
949 silc_buffer_free(idp);
951 /* Register pending command callback. After we've received the channel
952 information we will reprocess this command reply by re-calling this
953 USERS command reply callback. */
954 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
956 NULL, silc_server_command_reply_users, cmd);
961 /* Get the list count */
962 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
965 SILC_GET32_MSB(list_count, tmp);
967 /* Get Client ID list */
968 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
972 client_id_list = silc_buffer_alloc(tmp_len);
973 silc_buffer_pull_tail(client_id_list, tmp_len);
974 silc_buffer_put(client_id_list, tmp, tmp_len);
976 /* Get client mode list */
977 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
981 client_mode_list = silc_buffer_alloc(tmp_len);
982 silc_buffer_pull_tail(client_mode_list, tmp_len);
983 silc_buffer_put(client_mode_list, tmp, tmp_len);
985 /* Save the users to the channel */
986 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
987 client_id_list, client_mode_list,
990 silc_buffer_free(client_id_list);
991 silc_buffer_free(client_mode_list);
994 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
995 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
996 silc_free(channel_id);
997 silc_server_command_reply_free(cmd);
1000 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1002 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1003 SilcServer server = cmd->server;
1004 SilcCommandStatus status;
1005 SilcClientEntry client = NULL;
1006 SilcServerEntry server_entry = NULL;
1007 SilcClientID *client_id = NULL;
1008 SilcServerID *server_id = NULL;
1010 unsigned char *tmp, *pk;
1013 SilcIDPayload idp = NULL;
1015 SilcPublicKey public_key = NULL;
1017 COMMAND_CHECK_STATUS;
1019 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1022 idp = silc_id_payload_parse_data(tmp, len);
1026 /* Get the public key payload */
1027 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1031 /* Decode the public key */
1033 SILC_GET16_MSB(pk_len, tmp);
1034 SILC_GET16_MSB(type, tmp + 2);
1037 if (type != SILC_SKE_PK_TYPE_SILC)
1040 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1043 id_type = silc_id_payload_get_type(idp);
1044 if (id_type == SILC_ID_CLIENT) {
1045 client_id = silc_id_payload_get_id(idp);
1047 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1050 client = silc_idlist_find_client_by_id(server->global_list,
1051 client_id, TRUE, NULL);
1056 client->data.public_key = public_key;
1057 } else if (id_type == SILC_ID_SERVER) {
1058 server_id = silc_id_payload_get_id(idp);
1060 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1062 if (!server_entry) {
1063 server_entry = silc_idlist_find_server_by_id(server->global_list,
1064 server_id, TRUE, NULL);
1069 server_entry->data.public_key = public_key;
1075 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1076 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_GETKEY);
1078 silc_id_payload_free(idp);
1079 silc_free(client_id);
1080 silc_free(server_id);
1082 silc_pkcs_public_key_free(public_key);
1083 silc_server_command_reply_free(cmd);
1086 SILC_SERVER_CMD_REPLY_FUNC(list)
1088 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1089 SilcServer server = cmd->server;
1090 SilcCommandStatus status;
1091 SilcChannelID *channel_id = NULL;
1092 SilcChannelEntry channel;
1094 unsigned char *tmp, *name, *topic;
1095 uint32 usercount = 0;
1097 COMMAND_CHECK_STATUS_LIST;
1099 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1100 channel_id = silc_id_payload_parse_id(tmp, len);
1104 name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1105 topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1106 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1108 SILC_GET32_MSB(usercount, tmp);
1110 /* Add the channel entry if we do not have it already */
1111 channel = silc_idlist_find_channel_by_id(server->local_list,
1114 channel = silc_idlist_find_channel_by_id(server->global_list,
1117 /* If router did not find such Channel ID in its lists then this must
1118 be bogus channel or some router in the net is buggy. */
1119 if (server->server_type != SILC_SERVER)
1122 channel = silc_idlist_add_channel(server->global_list, strdup(name),
1123 SILC_CHANNEL_MODE_NONE, channel_id,
1132 silc_free(channel->topic);
1133 channel->topic = strdup(topic);
1136 /* Pending callbacks are not executed if this was an list entry */
1137 if (status != SILC_STATUS_OK &&
1138 status != SILC_STATUS_LIST_END) {
1139 silc_server_command_reply_free(cmd);
1144 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1145 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_LIST);
1146 silc_free(channel_id);
1147 silc_server_command_reply_free(cmd);