* Added silc_net_get_error_string, silc_net_listener_get_ip and
silc_net_listener_get_hostname to lib/silcutil/silcnet.[ch].
+ *
+
Tue Apr 10 15:55:42 CEST 2007 Jochen Eisinger <coffee@silcnet.org>
* Add option --enable-silc-plugin. Affected files are
#
# Author: Pekka Riikonen <priikone@silcnet.org>
#
-# Copyright (C) 2000 - 2005 Pekka Riikonen
+# Copyright (C) 2000 - 2007 Pekka Riikonen
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
sbin_PROGRAMS = silcd
silcd_SOURCES = \
- protocol.c \
+ serverconfig.c \
+ silcd.c \
+ server_version.c \
+ serverid.c \
route.c \
+ idlist.c \
+ server_query.c \
+ server.c \
packet_send.c \
packet_receive.c \
- idlist.c \
command.c \
command_reply.c \
- silcd.c \
- server.c \
server_util.c \
- server_backup.c \
- serverconfig.c \
- server_query.c \
- serverid.c \
- server_version.c
+ server_backup.c
LIBS = $(SILC_COMMON_LIBS)
LDADD =
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2005, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "server_internal.h"
static int silc_server_is_registered(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcServerCommandContext cmd,
SilcCommand command);
static void
usually cannot send commands hence the check. */
static int silc_server_is_registered(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcServerCommandContext cmd,
SilcCommand command)
{
- SilcIDListData idata = (SilcIDListData)sock->user_data;
+ SilcIDListData idata = silc_packet_get_context(sock);
if (!idata)
return FALSE;
SILC_TASK_CALLBACK(silc_server_command_process_timeout)
{
SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
- SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
+ SilcClientEntry client = silc_packet_get_context(timeout->ctx->sock);
if (!client) {
SILC_LOG_DEBUG(("Client entry is invalid"));
/* Processes received command packet. */
void silc_server_command_process(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
+ SilcIDListData idata = silc_packet_get_context(sock);
SilcServerCommandContext ctx;
SilcServerCommand *cmd;
SilcCommand command;
+ if (!idata)
+ return;
+
/* Allocate command context. This must be free'd by the
command routine receiving it. */
ctx = silc_server_command_alloc();
ctx->server = server;
- ctx->sock = silc_socket_dup(sock);
- ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
+ ctx->sock = sock;
+ ctx->packet = packet; /* Save original packet */
+ silc_packet_stream_ref(sock);
/* Parse the command payload in the packet */
- ctx->payload = silc_command_payload_parse(packet->buffer->data,
- packet->buffer->len);
+ ctx->payload = silc_command_payload_parse(packet->buffer.data,
+ silc_buffer_len(&packet->buffer));
if (!ctx->payload) {
- SILC_LOG_ERROR(("Bad command payload, dropped (%s:%d [%s])",
- sock->hostname, sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
- silc_packet_context_free(packet);
- silc_socket_free(ctx->sock);
+ SILC_LOG_ERROR(("Bad command payload"));
+ silc_packet_free(packet);
+ silc_packet_stream_unref(ctx->sock);
silc_free(ctx);
return;
}
SILC_LOG_DEBUG(("Unknown command %d", command));
silc_server_command_send_status_reply(ctx, command,
SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
- silc_server_command_free(ctx);
+ silc_packet_free(packet);
+ silc_packet_stream_unref(ctx->sock);
+ silc_free(ctx);
return;
}
executed with zero (0) timeout but if client is sending command more
frequently than once in 2 seconds, then the timeout may be 0 to 2
seconds. */
- if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
- SilcClientEntry client = (SilcClientEntry)sock->user_data;
+ if (idata->conn_type == SILC_CONN_CLIENT) {
+ SilcClientEntry client = silc_packet_get_context(sock);
SilcServerCommandTimeout timeout;
int fast;
- if (!client) {
- SILC_LOG_DEBUG(("Client entry is invalid"));
- silc_server_command_free(ctx);
- return;
- }
-
timeout = silc_calloc(1, sizeof(*timeout));
timeout->ctx = ctx;
timeout->cmd = cmd;
if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
(client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_command_process_timeout, timeout,
- (client->fast_command < 3 ? 0 :
- 2 - (time(NULL) - client->last_command)),
- (client->fast_command < 3 ? 200000 : 0),
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ silc_schedule_task_add_timeout(
+ server->schedule,
+ silc_server_command_process_timeout, timeout,
+ (client->fast_command < 3 ? 0 :
+ 2 - (time(NULL) - client->last_command)),
+ (client->fast_command < 3 ? 200000 : 0));
else
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_command_process_timeout, timeout,
- 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_command_process_timeout,
+ timeout, 0, 1);
return;
}
if (ctx->payload)
silc_command_payload_free(ctx->payload);
if (ctx->packet)
- silc_packet_context_free(ctx->packet);
+ silc_packet_free(ctx->packet);
if (ctx->sock)
- silc_socket_free(ctx->sock); /* Decrease reference counter */
+ silc_packet_stream_unref(ctx->sock);
silc_free(ctx);
}
}
SILC_COMMAND_RESERVED,
SILC_STATUS_ERR_TIMEDOUT, 0,
reply->ident, 0);
- cmdr->payload = silc_command_payload_parse(tmpreply->data, tmpreply->len);
+ cmdr->payload = silc_command_payload_parse(tmpreply->data,
+ silc_buffer_len(tmpreply));
silc_buffer_free(tmpreply);
/* Call all callbacks. Same as SILC_SERVER_PENDING_EXEC macro. */
specified command, ident, callback and context this function has no
effect. */
-bool silc_server_command_pending(SilcServer server,
+SilcBool silc_server_command_pending(SilcServer server,
SilcCommand reply_cmd,
SilcUInt16 ident,
SilcCommandCb callback,
/* Same as silc_server_command_pending with specific timeout for pending
commands. If the `timeout' is zero default timeout is used. */
-bool silc_server_command_pending_timed(SilcServer server,
+SilcBool silc_server_command_pending_timed(SilcServer server,
SilcCommand reply_cmd,
SilcUInt16 ident,
SilcCommandCb callback,
reply->context = context;
reply->callback = callback;
reply->timeout =
- silc_schedule_task_add(server->schedule, 0,
- silc_server_command_pending_timeout, reply,
- timeout ? timeout : 12, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_command_pending_timeout, reply,
+ timeout ? timeout : 12, 0);
silc_dlist_add(server->pending_commands, reply);
return TRUE;
0);
silc_server_packet_send(cmd->server, cmd->sock,
SILC_PACKET_COMMAND_REPLY, 0,
- buffer->data, buffer->len, FALSE);
+ buffer->data, silc_buffer_len(buffer));
silc_buffer_free(buffer);
}
1, arg_type, arg, arg_len);
silc_server_packet_send(cmd->server, cmd->sock,
SILC_PACKET_COMMAND_REPLY, 0,
- buffer->data, buffer->len, FALSE);
+ buffer->data, silc_buffer_len(buffer));
silc_buffer_free(buffer);
}
arg_type2, arg2, arg_len2);
silc_server_packet_send(cmd->server, cmd->sock,
SILC_PACKET_COMMAND_REPLY, 0,
- buffer->data, buffer->len, FALSE);
+ buffer->data, silc_buffer_len(buffer));
silc_buffer_free(buffer);
}
buffer = silc_command_payload_encode_payload(cmdr->payload);
silc_server_packet_send(cmd->server, cmd->sock,
SILC_PACKET_COMMAND_REPLY, 0,
- buffer->data, buffer->len, FALSE);
+ buffer->data, silc_buffer_len(buffer));
silc_buffer_free(buffer);
return TRUE;
}
SILC_SERVER_CMD_FUNC(nick)
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
SilcServer server = cmd->server;
SilcBuffer nidp, oidp = NULL;
SilcClientID *new_id;
unsigned char *nick, *nickc = NULL;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+ if (client->data.conn_type != SILC_CONN_CLIENT || !client)
goto out;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
/* Remove old cache entry */
- silc_idcache_del_by_context(server->local_list->clients, client);
+ silc_idcache_del_by_context(server->local_list->clients, client, NULL);
silc_free(client->id);
client->id = new_id;
/* Update client cache */
silc_idcache_add(server->local_list->clients, nickc,
- client->id, (void *)client, 0, NULL);
+ client->id, (void *)client);
nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
/* Send NICK_CHANGE notify to the client's channels */
silc_server_send_notify_on_channels(server, NULL, client,
SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
- oidp->data, oidp->len,
- nidp->data, nidp->len,
+ oidp->data, silc_buffer_len(oidp),
+ nidp->data, silc_buffer_len(nidp),
client->nickname,
strlen(client->nickname));
silc_server_send_command_reply(cmd->server, cmd->sock,
SILC_COMMAND_NICK,
SILC_STATUS_OK, 0, ident, 2,
- 2, nidp->data, nidp->len,
+ 2, nidp->data, silc_buffer_len(nidp),
3, nick, nick_len);
silc_buffer_free(nidp);
if (oidp)
/* Send the reply */
silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_LIST,
status, 0, ident, 4,
- 2, idp->data, idp->len,
+ 2, idp->data, silc_buffer_len(idp),
3, entry->channel_name,
strlen(entry->channel_name),
4, topic, topic ? strlen(topic) : 0,
/* Send the reply */
silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_LIST,
status, 0, ident, 4,
- 2, idp->data, idp->len,
+ 2, idp->data, silc_buffer_len(idp),
3, entry->channel_name,
strlen(entry->channel_name),
4, topic, topic ? strlen(topic) : 0,
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcChannelID *channel_id = NULL;
- unsigned char *tmp;
- SilcUInt32 tmp_len;
+ SilcID id;
SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
SilcUInt32 lch_count = 0, gch_count = 0;
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
SILC_PACKET_COMMAND, cmd->packet->flags,
- tmpbuf->data, tmpbuf->len, TRUE);
+ tmpbuf->data, silc_buffer_len(tmpbuf));
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_LIST,
}
/* Get Channel ID */
- tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
- if (tmp) {
- channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!channel_id) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
- SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
- goto out;
- }
+ if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
+ SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
+ goto out;
}
/* Get the channels from local list */
- lchannels = silc_idlist_get_channels(server->local_list, channel_id,
+ lchannels = silc_idlist_get_channels(server->local_list, SILC_ID_GET_ID(id),
&lch_count);
/* Get the channels from global list */
- gchannels = silc_idlist_get_channels(server->global_list, channel_id,
+ gchannels = silc_idlist_get_channels(server->global_list, SILC_ID_GET_ID(id),
&gch_count);
/* Send the reply */
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
- SilcChannelID *channel_id;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
+ SilcID id;
SilcChannelEntry channel;
SilcChannelClientEntry chl;
SilcBuffer idp;
SilcUInt32 argc, tmp_len;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+ if (client->data.conn_type != SILC_CONN_CLIENT || !client)
goto out;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
argc = silc_argument_get_arg_num(cmd->args);
/* Get Channel ID */
- tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
- if (!tmp) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
- SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
- goto out;
- }
- channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!channel_id) {
+ if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
goto out;
/* Check whether the channel exists */
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
0, 2, tmp, tmp_len);
if (argc > 1) {
/* Get the topic */
- tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
+ tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
if (!tmp) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
0);
goto out;
}
-
- if (strlen(tmp) > 256) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
- 0);
- goto out;
+ if (tmp_len > 256) {
+ tmp_len = 256;
+ tmp[tmp_len - 1] = '\0';
}
- if (!silc_utf8_valid(tmp, strlen(tmp))) {
+ if (!silc_utf8_valid(tmp, tmp_len)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
0);
idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
SILC_NOTIFY_TYPE_TOPIC_SET, 2,
- idp->data, idp->len,
+ idp->data, silc_buffer_len(idp),
channel->topic,
strlen(channel->topic));
silc_buffer_free(idp);
}
/* Send the topic to client as reply packet */
- idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
+ idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_TOPIC,
SILC_STATUS_OK, 0, ident, 2,
- 2, idp->data, idp->len,
+ 2, idp->data, silc_buffer_len(idp),
3, channel->topic,
channel->topic ?
strlen(channel->topic) : 0);
silc_buffer_free(idp);
- silc_free(channel_id);
out:
silc_server_command_free(cmd);
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcSocketConnection sock = cmd->sock, dest_sock;
+ SilcPacketStream sock = cmd->sock, dest_sock;
SilcChannelClientEntry chl;
SilcClientEntry sender, dest;
- SilcClientID *dest_id = NULL;
SilcChannelEntry channel;
- SilcChannelID *channel_id = NULL;
+ SilcID id, id2;
SilcIDListData idata;
SilcArgumentPayload args;
SilcHashTableList htl;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
/* Get Channel ID */
- tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
- if (!tmp) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
- SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
- goto out;
- }
- channel_id = silc_id_payload_parse_id(tmp, len, NULL);
- if (!channel_id) {
+ if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
goto out;
/* Get the channel entry */
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
0, 2, tmp, len);
}
/* Check whether the sender of this command is on the channel. */
- sender = (SilcClientEntry)sock->user_data;
+ sender = silc_packet_get_context(sock);
if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
2, tmp, len);
if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
SILC_STATUS_ERR_NO_CHANNEL_PRIV,
0, 2, tmp, len);
}
/* Get destination client ID */
- tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
- if (tmp) {
- bool resolve;
-
- dest_id = silc_id_payload_parse_id(tmp, len, NULL);
- if (!dest_id) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
- SILC_STATUS_ERR_NO_CLIENT_ID, 0);
- goto out;
- }
+ if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id2, NULL)) {
+ SilcBool resolve;
/* Get the client entry */
- dest = silc_server_query_client(server, dest_id, FALSE, &resolve);
+ dest = silc_server_query_client(server, SILC_ID_GET_ID(id2),
+ FALSE, &resolve);
if (!dest) {
if (server->server_type != SILC_SERVER || !resolve || cmd->pending) {
+ tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
silc_server_command_send_status_data(
cmd, SILC_COMMAND_INVITE,
SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
/* Check whether the requested client is already on the channel. */
if (silc_server_client_on_channel(dest, channel, NULL)) {
+ tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
atype = silc_argument_get_arg_type(cmd->args, 1, &len2);
silc_server_command_send_status_data2(cmd, SILC_COMMAND_INVITE,
SILC_STATUS_ERR_USER_ON_CHANNEL,
}
/* Get route to the client */
- dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
+ dest_sock = silc_server_get_client_route(server, NULL, 0,
+ SILC_ID_GET_ID(id2),
&idata, NULL);
if (!dest_sock) {
+ tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
0, 2, tmp, len);
silc_server_inviteban_destruct, channel, TRUE);
/* Check if the ID is in the list already */
+ tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
silc_hash_table_list(channel->invite_list, &htl);
while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
/* Send notify to the client that is invited to the channel */
SilcBuffer idp, idp2;
- idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
+ idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
- silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
- SILC_ID_CLIENT,
+ silc_server_send_notify_dest(server, dest_sock, FALSE,
+ SILC_ID_GET_ID(id2), SILC_ID_CLIENT,
SILC_NOTIFY_TYPE_INVITE, 3,
- idp->data, idp->len,
+ idp->data, silc_buffer_len(idp),
channel->channel_name,
strlen(channel->channel_name),
- idp2->data, idp2->len);
+ idp2->data, silc_buffer_len(idp2));
silc_buffer_free(idp);
silc_buffer_free(idp2);
}
SILC_STR_END);
silc_hash_table_list(channel->invite_list, &htl);
while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
- list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
- type);
+ list = silc_argument_payload_encode_one(list, tmp2->data,
+ silc_buffer_len(tmp2), type);
silc_hash_table_list_reset(&htl);
}
/* Send to local servers if we are router */
if (server->server_type == SILC_ROUTER) {
SilcBuffer idp, idp2;
- idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
+ idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
SILC_NOTIFY_TYPE_INVITE, 5,
- idp->data, idp->len,
+ idp->data, silc_buffer_len(idp),
channel->channel_name,
strlen(channel->channel_name),
- idp2->data, idp2->len,
+ idp2->data, silc_buffer_len(idp2),
atype, 1,
tmp ? alist.data : NULL,
- tmp ? alist.len : 0);
+ tmp ? silc_buffer_len(&alist) : 0);
silc_buffer_free(idp);
silc_buffer_free(idp2);
}
2, tmp, len,
3, type && list ?
list->data : NULL,
- type && list ? list->len : 0);
+ type && list ? silc_buffer_len(list) : 0);
silc_buffer_free(list);
out:
- silc_free(dest_id);
- silc_free(channel_id);
silc_server_command_free(cmd);
}
typedef struct {
- SilcSocketConnection sock;
+ SilcPacketStream sock;
char *signoff;
} *QuitInternal;
{
SilcServer server = app_context;
QuitInternal q = (QuitInternal)context;
+ SilcClientEntry client = silc_packet_get_context(q->sock);
- if (q->sock->user_data) {
+ if (client) {
/* Free all client specific data, such as client entry and entires
on channels this client may be on. */
- silc_server_free_client_data(server, q->sock, q->sock->user_data,
+ silc_server_free_client_data(server, q->sock, client,
TRUE, q->signoff);
- q->sock->user_data = NULL;
+ silc_packet_set_context(q->sock, NULL);
}
- if (!SILC_IS_DISCONNECTED(q->sock))
- /* Close the connection on our side */
- silc_server_close_connection(server, q->sock);
-
- silc_socket_free(q->sock);
+ silc_packet_stream_unref(q->sock);
silc_free(q->signoff);
silc_free(q);
}
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcSocketConnection sock = cmd->sock;
+ SilcPacketStream sock = cmd->sock;
+ SilcClientEntry client = silc_packet_get_context(sock);
QuitInternal q;
unsigned char *tmp = NULL;
SilcUInt32 len = 0;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+ if (client->data.conn_type != SILC_CONN_CLIENT)
goto out;
/* Get message */
tmp = NULL;
q = silc_calloc(1, sizeof(*q));
- q->sock = silc_socket_dup(sock);
+ q->sock = sock;
q->signoff = tmp ? strdup(tmp) : NULL;
+ silc_packet_stream_ref(q->sock);
/* We quit the connection with little timeout */
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_command_quit_cb, (void *)q,
- 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_command_quit_cb, (void *)q,
+ 0, 200000);
out:
silc_server_command_free(cmd);
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
SilcClientEntry remote_client;
- SilcClientID *client_id = NULL;
+ SilcID id;
unsigned char *tmp, *comment, *auth;
SilcUInt32 tmp_len, tmp_len2, auth_len;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+ if (client->data.conn_type != SILC_CONN_CLIENT || !client)
goto out;
/* Get authentication payload if present */
}
/* Get the client ID */
- tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
- if (!tmp) {
+ if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
- 0);
- goto out;
- }
- client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!client_id) {
- silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
- SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
- 0, 2, tmp, tmp_len);
+ SILC_STATUS_ERR_NO_CLIENT_ID, 0);
goto out;
}
/* Get the client entry */
remote_client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, NULL);
+ SILC_ID_GET_ID(id),
+ TRUE, NULL);
if (!remote_client) {
remote_client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
+ SILC_ID_GET_ID(id),
+ TRUE, NULL);
if (!remote_client) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
0, 2, tmp, tmp_len);
/* If authentication data is provided then verify that killing is
actually allowed */
if (auth && auth_len) {
- SilcSocketConnection sock;
+ SilcPacketStream sock;
if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
}
/* Send reply to the sender */
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
SILC_STATUS_OK, 0,
2, tmp, tmp_len);
/* Router operator killing */
/* Send reply to the sender */
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
SILC_STATUS_OK, 0,
2, tmp, tmp_len);
}
out:
- silc_free(client_id);
silc_server_command_free(cmd);
}
char *dest_server = NULL, *server_info = NULL, *server_name;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
SilcServerEntry entry = NULL;
- SilcServerID *server_id = NULL;
+ SilcID id;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
}
/* Get Server ID */
- tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
- if (tmp) {
- server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!server_id) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
- SILC_STATUS_ERR_NO_SERVER_ID, 0);
- goto out;
- }
- }
-
- if (server_id) {
+ if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL)) {
/* Check whether we have this server cached */
entry = silc_idlist_find_server_by_id(server->local_list,
- server_id, TRUE, NULL);
+ SILC_ID_GET_ID(id), TRUE, NULL);
if (!entry) {
entry = silc_idlist_find_server_by_id(server->global_list,
- server_id, TRUE, NULL);
+ SILC_ID_GET_ID(id), TRUE, NULL);
if (!entry && server->server_type != SILC_SERVER) {
+ tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
0, 2, tmp, tmp_len);
}
}
- /* Some buggy servers has sent request to router about themselves. */
- if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
- goto out;
-
- if ((!dest_server && !server_id && !entry) || (entry &&
- entry == server->id_entry) ||
+ if ((!dest_server && !entry) || (entry && entry == server->id_entry) ||
(dest_server && !cmd->pending &&
!memcmp(dest_server, server->server_name, strlen(dest_server)))) {
/* Send our reply */
silc_server_packet_send(server, entry->connection,
SILC_PACKET_COMMAND, cmd->packet->flags,
- tmpbuf->data, tmpbuf->len, TRUE);
+ tmpbuf->data, silc_buffer_len(tmpbuf));
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_INFO,
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
SILC_PACKET_COMMAND, cmd->packet->flags,
- tmpbuf->data, tmpbuf->len, TRUE);
+ tmpbuf->data, silc_buffer_len(tmpbuf));
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_INFO,
}
}
- silc_free(server_id);
-
if (!entry) {
if (dest_server) {
silc_free(dest_server);
/* Send the reply */
silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_INFO,
SILC_STATUS_OK, 0, ident, 3,
- 2, idp->data, idp->len,
+ 2, idp->data, silc_buffer_len(idp),
3, server_name,
strlen(server_name),
4, server_info,
SilcServer server = cmd->server;
SilcUInt32 tmp_len;
unsigned char *tmp;
- SilcServerID *server_id = NULL;
+ SilcID id;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
/* Get Server ID */
- tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
- if (!tmp) {
+ if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
0);
goto out;
}
- server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!server_id)
- goto out;
- if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
+ if (SILC_ID_SERVER_COMPARE(SILC_ID_GET_ID(id), server->id)) {
/* Send our reply */
silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
SILC_STATUS_OK, 0);
} else {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_PING,
SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
2, tmp, tmp_len);
}
out:
- silc_free(server_id);
silc_server_command_free(cmd);
}
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcServerID *server_id;
+ SilcID id;
unsigned char *tmp;
SilcUInt32 tmp_len;
SilcBuffer packet, stats;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
/* Get Server ID */
- tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
- if (!tmp) {
+ if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_STATS,
SILC_STATUS_ERR_NO_SERVER_ID, 0);
goto out;
}
- server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!server_id)
- goto out;
/* The ID must be ours */
- if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
+ if (!SILC_ID_SERVER_COMPARE(server->id, SILC_ID_GET_ID(id))) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_STATS,
SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
2, tmp, tmp_len);
- silc_free(server_id);
goto out;
}
- silc_free(server_id);
/* If we are router then just send everything we got. If we are normal
server then we'll send this to our router to get all the latest
SILC_ID_SERVER);
packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
++server->cmd_ident, 1,
- 1, idp->data, idp->len);
+ 1, idp->data,
+ silc_buffer_len(idp));
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
SILC_PACKET_COMMAND, 0, packet->data,
- packet->len, FALSE);
+ silc_buffer_len(packet));
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_STATS,
SILC_STR_UI_INT(server->stat.router_ops),
SILC_STR_END);
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_STATS,
SILC_STATUS_OK, 0, ident, 2,
2, tmp, tmp_len,
- 3, stats->data, stats->len);
+ 3, stats->data, silc_buffer_len(stats));
silc_buffer_free(stats);
out:
SilcServerCommandContext cmd,
SilcChannelEntry channel,
SilcClientID *client_id,
- bool created,
- bool create_key,
+ SilcBool created,
+ SilcBool create_key,
SilcUInt32 umode,
const unsigned char *auth,
SilcUInt32 auth_len,
const unsigned char *cauth,
SilcUInt32 cauth_len)
{
- SilcSocketConnection sock = cmd->sock;
+ SilcPacketStream sock = cmd->sock;
+ SilcIDListData idata = silc_packet_get_context(sock);
unsigned char *tmp;
SilcUInt32 tmp_len, user_count;
unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4], ulimit[4];
SilcBuffer user_list, mode_list, invite_list, ban_list;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
char check[512], check2[512];
- bool founder = FALSE;
- bool resolve;
+ SilcBool founder = FALSE;
+ SilcBool resolve;
SilcBuffer fkey = NULL, chpklist = NULL;
- const char *cipher;
+ const char *cipher, *hostname, *ip;
SILC_LOG_DEBUG(("Joining client to channel"));
if (!channel)
return;
+ silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
+
/* Get the client entry */
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
- client = (SilcClientEntry)sock->user_data;
+ if (idata->conn_type == SILC_CONN_CLIENT) {
+ client = (SilcClientEntry)idata;
if (!client)
return;
} else {
clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
silc_server_send_command(server, cmd->sock,
SILC_COMMAND_GETKEY, ++server->cmd_ident,
- 1, 1, clidp->data, clidp->len);
+ 1, 1, clidp->data, silc_buffer_len(clidp));
silc_buffer_free(clidp);
silc_server_command_pending(server, SILC_COMMAND_GETKEY,
server->cmd_ident,
if (!strchr(client->username, '@')) {
silc_strncat(check, sizeof(check), "@", 1);
silc_strncat(check, sizeof(check),
- cmd->sock->hostname, strlen(cmd->sock->hostname));
+ hostname, strlen(hostname));
}
silc_strncat(check2, sizeof(check2),
if (!strchr(client->username, '@')) {
silc_strncat(check2, sizeof(check2), "@", 1);
silc_strncat(check2, sizeof(check2),
- cmd->sock->hostname, strlen(cmd->sock->hostname));
+ hostname, strlen(hostname));
}
/* Check invite list if channel is invite-only channel */
chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_NOT_INVITED, 0,
- 2, chidp->data, chidp->len);
+ 2, chidp->data,
+ silc_buffer_len(chidp));
silc_buffer_free(chidp);
goto out;
}
silc_server_command_send_status_data(
cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0,
- 2, chidp->data, chidp->len);
+ 2, chidp->data,
+ silc_buffer_len(chidp));
silc_buffer_free(chidp);
goto out;
}
chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_CHANNEL_IS_FULL,
- 0, 2, chidp->data, chidp->len);
+ 0, 2, chidp->data,
+ silc_buffer_len(chidp));
silc_buffer_free(chidp);
goto out;
}
chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_BAD_PASSWORD, 0,
- 2, chidp->data, chidp->len);
+ 2, chidp->data,
+ silc_buffer_len(chidp));
silc_buffer_free(chidp);
goto out;
}
chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
silc_server_command_send_status_data2(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_USER_ON_CHANNEL, 0,
- 2, clidp->data, clidp->len,
- 3, chidp->data, chidp->len);
+ 2, clidp->data,
+ silc_buffer_len(clidp),
+ 3, chidp->data,
+ silc_buffer_len(chidp));
silc_buffer_free(clidp);
silc_buffer_free(chidp);
goto out;
SILC_PUT32_MSB(channel->user_limit, ulimit);
if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
- tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- cipher = silc_cipher_get_name(channel->channel_key);
- keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
- SILC_ID_CHANNEL),
- tmp,
+ unsigned char cid[32];
+ SilcUInt32 cid_len;
+ silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid), &cid_len);
+ cipher = silc_cipher_get_name(channel->send_key);
+ keyp = silc_channel_key_payload_encode(cid_len, cid,
strlen(cipher), cipher,
channel->key_len / 8, channel->key);
- silc_free(tmp);
}
if (channel->founder_key)
- fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
+ fkey = silc_public_key_payload_encode(channel->founder_key);
/* Encode invite list */
invite_list = NULL;
while (silc_hash_table_get(&htl, (void *)&tmp_len, (void *)&reply))
invite_list = silc_argument_payload_encode_one(invite_list,
reply->data,
- reply->len, tmp_len);
+ silc_buffer_len(reply), tmp_len);
silc_hash_table_list_reset(&htl);
}
while (silc_hash_table_get(&htl, (void *)&tmp_len, (void *)&reply))
ban_list = silc_argument_payload_encode_one(ban_list,
reply->data,
- reply->len, tmp_len);
+ silc_buffer_len(reply), tmp_len);
silc_hash_table_list_reset(&htl);
}
SILC_STATUS_OK, 0, ident, 16,
2, channel->channel_name,
strlen(channel->channel_name),
- 3, chidp->data, chidp->len,
- 4, clidp->data, clidp->len,
+ 3, chidp->data,
+ silc_buffer_len(chidp),
+ 4, clidp->data,
+ silc_buffer_len(clidp),
5, mode, 4,
6, tmp2, 4,
7, keyp ? keyp->data : NULL,
- keyp ? keyp->len : 0,
+ keyp ? silc_buffer_len(keyp) : 0,
8, ban_list ? ban_list->data : NULL,
- ban_list ? ban_list->len : 0,
+ ban_list ?
+ silc_buffer_len(ban_list): 0,
9, invite_list ? invite_list->data :
NULL,
- invite_list ? invite_list->len : 0,
+ invite_list ?
+ silc_buffer_len(invite_list) : 0,
10, channel->topic,
channel->topic ?
strlen(channel->topic) : 0,
strlen(silc_hmac_get_name(channel->
hmac)),
12, tmp3, 4,
- 13, user_list->data, user_list->len,
+ 13, user_list->data,
+ silc_buffer_len(user_list),
14, mode_list->data,
- mode_list->len,
+ silc_buffer_len(mode_list),
15, fkey ? fkey->data : NULL,
- fkey ? fkey->len : 0,
+ fkey ? silc_buffer_len(fkey) : 0,
16, chpklist ? chpklist->data : NULL,
- chpklist ? chpklist->len : 0,
+ chpklist ? silc_buffer_len(chpklist) : 0,
17, (channel->mode &
SILC_CHANNEL_MODE_ULIMIT ?
ulimit : NULL),
/* Send command reply */
silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
- reply->data, reply->len, FALSE);
+ reply->data, silc_buffer_len(reply));
/* Statistics */
cmd->server->stat.commands_sent++;
SILC_LOG_DEBUG(("Send JOIN notify to channel"));
silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
SILC_NOTIFY_TYPE_JOIN, 2,
- clidp->data, clidp->len,
- chidp->data, chidp->len);
+ clidp->data, silc_buffer_len(clidp),
+ chidp->data, silc_buffer_len(chidp));
/* Update statistics */
server->stat.my_chanclients++;
if (keyp)
/* Distribute the channel key to all backup routers. */
silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
- keyp->data, keyp->len, FALSE, TRUE);
+ keyp->data, silc_buffer_len(keyp), FALSE, TRUE);
/* If client became founder by providing correct founder auth data
notify the mode change to the channel. */
SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
- clidp->data, clidp->len,
- mode, 4, clidp->data, clidp->len,
+ clidp->data,
+ silc_buffer_len(clidp),
+ mode, 4, clidp->data,
+ silc_buffer_len(clidp),
fkey ? fkey->data : NULL,
- fkey ? fkey->len : 0);
+ fkey ? silc_buffer_len(fkey) : 0);
}
}
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
+ SilcIDListData idata = silc_packet_get_context(cmd->sock);
unsigned char *auth, *cauth;
SilcUInt32 tmp_len, auth_len, cauth_len;
char *tmp, *channel_name, *channel_namec = NULL, *cipher, *hmac;
SilcChannelEntry channel;
SilcUInt32 umode = 0;
- bool created = FALSE, create_key = TRUE;
- SilcClientID *client_id;
+ SilcBool created = FALSE, create_key = TRUE;
+ SilcID id;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 7);
/* Truncate over long channel names */
if (tmp_len > 256) {
- tmp[256] = '\0';
+ tmp[tmp_len - 1] = '\0';
tmp_len = 256;
}
channel_name = tmp;
}
/* Get Client ID of the client who is joining to the channel */
- tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
- if (!tmp) {
+ if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_NO_CLIENT_ID,
0);
goto out;
}
- client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!client_id) {
- silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
- SILC_STATUS_ERR_BAD_CLIENT_ID, 0,
- 2, tmp, tmp_len);
- goto out;
- }
+ tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
/* Get cipher, hmac name and auth payload */
cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
channel = silc_idlist_find_channel_by_name(server->local_list,
channel_namec, NULL);
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
- SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
+ if (idata->conn_type == SILC_CONN_CLIENT) {
+ SilcClientEntry entry = (SilcClientEntry)idata;
if (!entry) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
}
#endif /* SILC_DIST_INPLACE */
- silc_free(client_id);
- client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
-
if (!channel ||
(channel->disabled && server->server_type != SILC_ROUTER)) {
/* Channel not found or not valid */
cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
0, 2, cipher, strlen(cipher));
- silc_free(client_id);
goto out;
}
/* If this is pending command callback then we've resolved
it and it didn't work, return since we've notified the
client already in the command reply callback. */
- if (cmd->pending) {
- silc_free(client_id);
+ if (cmd->pending)
goto out;
- }
/* Statistics */
cmd->server->stat.commands_sent++;
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
/* Send JOIN command to our router */
- silc_server_packet_send(server, (SilcSocketConnection)
- SILC_PRIMARY_ROUTE(server),
+ silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
SILC_PACKET_COMMAND, cmd->packet->flags,
- tmpbuf->data, tmpbuf->len, TRUE);
+ tmpbuf->data, silc_buffer_len(tmpbuf));
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_JOIN,
cmd->pending = TRUE;
silc_command_set_ident(cmd->payload, old_ident);
silc_buffer_free(tmpbuf);
- silc_free(client_id);
goto out;
}
cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2, cipher, strlen(cipher));
- silc_free(client_id);
goto out;
}
/* If the command came from router and we are normal server then
something went wrong with the joining as the channel was not found.
We can't do anything else but ignore this. */
- if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
- server->server_type != SILC_ROUTER) {
- silc_free(client_id);
+ if (idata->conn_type == SILC_CONN_ROUTER ||
+ server->server_type != SILC_ROUTER)
goto out;
- }
/* We are router and the channel does not seem exist so we will check
our global list as well for the channel. */
cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2, cipher, strlen(cipher));
- silc_free(client_id);
goto out;
}
umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
/* Join to the channel */
- silc_server_command_join_channel(server, cmd, channel, client_id,
+ silc_server_command_join_channel(server, cmd, channel, SILC_ID_GET_ID(id),
created, create_key, umode,
auth, auth_len, cauth, cauth_len);
- silc_free(client_id);
-
out:
silc_free(channel_namec);
silc_server_command_free(cmd);
/* No motd */
silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
SILC_STATUS_OK, 0, ident, 1,
- 2, idp->data, idp->len);
+ 2, idp->data, silc_buffer_len(idp));
goto out;
}
motd[motd_len] = 0;
silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
SILC_STATUS_OK, 0, ident, 2,
- 2, idp->data, idp->len,
+ 2, idp->data, silc_buffer_len(idp),
3, motd, motd_len);
} else {
/* No motd */
silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
SILC_STATUS_OK, 0, ident, 1,
- 2, idp->data, idp->len);
+ 2, idp->data, silc_buffer_len(idp));
}
silc_buffer_free(idp);
} else {
silc_server_packet_send(server, entry->connection,
SILC_PACKET_COMMAND, cmd->packet->flags,
- tmpbuf->data, tmpbuf->len, TRUE);
+ tmpbuf->data, silc_buffer_len(tmpbuf));
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_MOTD,
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
SILC_PACKET_COMMAND, cmd->packet->flags,
- tmpbuf->data, tmpbuf->len, TRUE);
+ tmpbuf->data, silc_buffer_len(tmpbuf));
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_MOTD,
idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
SILC_STATUS_OK, 0, ident, 2,
- 2, idp->data, idp->len,
+ 2, idp->data, silc_buffer_len(idp),
3, entry->motd,
entry->motd ?
strlen(entry->motd) : 0);
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
unsigned char *tmp_mask, m[4];
SilcUInt32 mask = 0;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
- bool set_mask = FALSE;
+ SilcBool set_mask = FALSE;
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+ if (client->data.conn_type != SILC_CONN_CLIENT || !client)
goto out;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
SilcIDListData idata = (SilcIDListData)client;
- SilcChannelID *channel_id = NULL;
+ SilcID id;
SilcChannelEntry channel;
SilcChannelClientEntry chl;
SilcBuffer cidp;
char *cipher = NULL, *hmac = NULL, *passphrase = NULL, ulimit[4];
SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2, chpklen;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
- bool set_mask = FALSE, set_chpk = FALSE;
+ SilcBool set_mask = FALSE, set_chpk = FALSE;
SilcPublicKey founder_key = NULL;
SilcBuffer fkey = NULL, chpklist = NULL;
SilcBufferStruct chpk;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 9);
/* Get Channel ID */
- tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
- if (!tmp_id) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
- SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
- silc_server_command_free(cmd);
- return;
- }
- channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
- if (!channel_id) {
+ if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
silc_server_command_free(cmd);
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
+ tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
0, 2, tmp_id, tmp_len2);
- silc_free(channel_id);
silc_server_command_free(cmd);
return;
}
/* Check whether this client is on the channel */
if (!silc_server_client_on_channel(client, channel, &chl)) {
+ tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
2, tmp_id, tmp_len2);
if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
mode_mask)) {
SILC_LOG_DEBUG(("Client does not have rights to change mode"));
+ tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
silc_server_command_send_status_data(
cmd, SILC_COMMAND_CMODE,
(!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
unsigned char m[4];
SILC_PUT32_MSB(channel->mode, m);
if (channel->founder_key)
- fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
+ fkey = silc_public_key_payload_encode(channel->founder_key);
if (channel->channel_pubkeys)
chpklist = silc_server_get_channel_pk_list(server, channel,
FALSE, FALSE);
+ tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
SILC_STATUS_OK, 0, ident, 4,
2, tmp_id, tmp_len2,
3, m, sizeof(m),
4, fkey ? fkey->data : NULL,
- fkey ? fkey->len : 0,
+ fkey ? silc_buffer_len(fkey) : 0,
5, chpklist ? chpklist->data : NULL,
- chpklist ? chpklist->len : 0);
+ chpklist ? silc_buffer_len(chpklist) : 0);
goto out;
}
server->server_type == SILC_ROUTER ?
FALSE : !server->standalone);
- cipher = (char *)silc_cipher_get_name(channel->channel_key);
+ cipher = (char *)silc_cipher_get_name(channel->send_key);
hmac = (char *)silc_hmac_get_name(channel->hmac);
}
}
if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
/* Cipher to use protect the traffic */
- SilcCipher newkey, oldkey;
+ SilcCipher send_key, receive_key, olds, oldr;
/* Get cipher */
cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
}
/* Delete old cipher and allocate the new one */
- if (!silc_cipher_alloc(cipher, &newkey)) {
+ if (!silc_cipher_alloc(cipher, &send_key)) {
+ silc_server_command_send_status_data(
+ cmd, SILC_COMMAND_CMODE,
+ SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
+ 2, cipher, strlen(cipher));
+ goto out;
+ }
+ if (!silc_cipher_alloc(cipher, &receive_key)) {
silc_server_command_send_status_data(
cmd, SILC_COMMAND_CMODE,
SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
goto out;
}
- oldkey = channel->channel_key;
- channel->channel_key = newkey;
+ olds = channel->send_key;
+ oldr = channel->receive_key;
+ channel->send_key = send_key;
+ channel->receive_key = receive_key;
/* Re-generate channel key */
if (!silc_server_create_channel_key(server, channel, 0)) {
/* We don't have new key, revert to old one */
- channel->channel_key = oldkey;
+ channel->send_key = olds;
+ channel->receive_key = oldr;
goto out;
}
/* Remove old channel key for good */
- silc_cipher_free(oldkey);
+ silc_cipher_free(olds);
+ silc_cipher_free(oldr);
/* Send the channel key. This sends it to our local clients and if
we are normal server to our router as well. */
if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
/* Cipher mode is unset. Remove the cipher and revert back to
default cipher */
- SilcCipher newkey, oldkey;
+ SilcCipher send_key, receive_key, olds, oldr;
cipher = channel->cipher;
/* Delete old cipher and allocate default one */
- if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
+ if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
+ &send_key)) {
+ silc_server_command_send_status_data(
+ cmd, SILC_COMMAND_CMODE,
+ SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
+ 2, cipher, strlen(cipher));
+ goto out;
+ }
+ if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
+ &receive_key)) {
silc_server_command_send_status_data(
cmd, SILC_COMMAND_CMODE,
SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
goto out;
}
- oldkey = channel->channel_key;
- channel->channel_key = newkey;
+ olds = channel->send_key;
+ oldr = channel->receive_key;
+ channel->send_key = send_key;
+ channel->receive_key = receive_key;
/* Re-generate channel key */
if (!silc_server_create_channel_key(server, channel, 0)) {
/* We don't have new key, revert to old one */
- channel->channel_key = oldkey;
+ channel->send_key = olds;
+ channel->receive_key = oldr;
goto out;
}
/* Remove old channel key for good */
- silc_cipher_free(oldkey);
+ silc_cipher_free(olds);
+ silc_cipher_free(oldr);
/* Send the channel key. This sends it to our local clients and if
we are normal server to our router as well. */
founder_key = idata->public_key;
tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
if (tmp) {
- if (!silc_pkcs_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
+ if (!silc_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
SILC_STATUS_ERR_AUTH_FAILED,
0);
goto out;
}
- fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
+ fkey = silc_public_key_payload_encode(channel->founder_key);
if (!fkey) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
SILC_STATUS_ERR_AUTH_FAILED,
SILC_PUT32_MSB(channel->user_limit, ulimit);
silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
- cidp->data, cidp->len,
+ cidp->data, silc_buffer_len(cidp),
tmp_mask, 4,
cipher, cipher ? strlen(cipher) : 0,
hmac, hmac ? strlen(hmac) : 0,
passphrase, passphrase ?
strlen(passphrase) : 0,
fkey ? fkey->data : NULL,
- fkey ? fkey->len : 0,
+ fkey ? silc_buffer_len(fkey) : 0,
chpkdata ? chpkdata : NULL,
chpkdata ? chpklen : 0,
mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
/* Send command reply to sender */
+ tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
SILC_STATUS_OK, 0, ident, 5,
2, tmp_id, tmp_len2,
3, tmp_mask, 4,
4, fkey ? fkey->data : NULL,
- fkey ? fkey->len : 0,
+ fkey ? silc_buffer_len(fkey) : 0,
5, chpklist ? chpklist->data :
- NULL, chpklist ? chpklist->len
+ NULL, chpklist ? silc_buffer_len(chpklist)
: 0,
6, (mode_mask &
SILC_CHANNEL_MODE_ULIMIT ?
channel->mode = old_mask;
silc_buffer_free(chpklist);
silc_buffer_free(fkey);
- silc_free(channel_id);
silc_server_command_free(cmd);
}
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
- SilcChannelID *channel_id = NULL;
- SilcClientID *client_id = NULL;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
+ SilcID id, id2;
SilcChannelEntry channel;
SilcClientEntry target_client;
SilcChannelClientEntry chl;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
/* Get Channel ID */
- tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
- if (!tmp_ch_id) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
- SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
- goto out;
- }
- channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
- if (!channel_id) {
+ if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
goto out;
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
+ tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
0, 2, tmp_ch_id, tmp_ch_len);
/* Check whether sender is on the channel */
if (!silc_server_client_on_channel(client, channel, &chl)) {
+ tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
2, tmp_ch_id, tmp_ch_len);
SILC_GET32_MSB(target_mask, tmp_mask);
/* Get target Client ID */
- tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
- if (!tmp_id) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
- SILC_STATUS_ERR_NO_CLIENT_ID, 0);
- goto out;
- }
- client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
- if (!client_id) {
+ if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id2, NULL)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_NO_CLIENT_ID, 0);
goto out;
/* Get target client's entry */
target_client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, NULL);
+ SILC_ID_GET_ID(id2),
+ TRUE, NULL);
if (!target_client)
target_client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
+ SILC_ID_GET_ID(id2),
+ TRUE, NULL);
if (target_client != client &&
!(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
!(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
+ tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_NOT_YOU, 0,
2, tmp_ch_id, tmp_ch_len);
/* Check whether target client is on the channel */
if (target_client != client) {
if (!silc_server_client_on_channel(target_client, channel, &chl)) {
+ tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
+ tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
silc_server_command_send_status_data2(
cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0,
/* If the target client is founder, no one else can change their mode
but themselves. */
if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
+ tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
0, 2, tmp_ch_id, tmp_ch_len);
notify = TRUE;
founder_key = channel->founder_key;
- fkey = silc_pkcs_public_key_payload_encode(founder_key);
+ fkey = silc_public_key_payload_encode(founder_key);
if (!fkey) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_AUTH_FAILED, 0);
if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
!(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
+ tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_NO_CHANNEL_PRIV,
0, 2, tmp_ch_id, tmp_ch_len);
if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
!(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
+ tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_NO_CHANNEL_PRIV,
0, 2, tmp_ch_id, tmp_ch_len);
idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
+ tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
/* Send notify to channel, notify only if mode was actually changed. */
if (notify) {
silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
- idp->data, idp->len,
+ idp->data, silc_buffer_len(idp),
tmp_mask, 4,
tmp_id, tmp_len,
fkey ? fkey->data : NULL,
- fkey ? fkey->len : 0);
+ fkey ? silc_buffer_len(fkey) : 0);
/* Set CUMODE notify type to network */
silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
silc_buffer_free(idp);
out:
- silc_free(channel_id);
- silc_free(client_id);
silc_buffer_free(fkey);
silc_server_command_free(cmd);
}
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
SilcClientEntry target_client;
- SilcChannelID *channel_id;
- SilcClientID *client_id;
+ SilcID id, id2;
SilcChannelEntry channel;
SilcChannelClientEntry chl;
SilcBuffer idp;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
/* Get Channel ID */
- tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
- if (!tmp) {
+ if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
goto out;
}
- channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!channel_id) {
- silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
- SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
- 2, tmp, tmp_len);
- goto out;
- }
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
0, 2, tmp, tmp_len);
/* Check whether sender is on the channel */
if (!silc_server_client_on_channel(client, channel, &chl)) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
SILC_STATUS_ERR_NOT_ON_CHANNEL,
0, 2, tmp, tmp_len);
/* Check that the kicker is channel operator or channel founder */
if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
SILC_STATUS_ERR_NO_CHANNEL_PRIV,
0, 2, tmp, tmp_len);
}
/* Get target Client ID */
- target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
- if (!target_idp) {
+ if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id2, NULL)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
SILC_STATUS_ERR_NO_CLIENT_ID, 0);
goto out;
}
- client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
- if (!client_id) {
- silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
- SILC_STATUS_ERR_BAD_CLIENT_ID,
- 0, 2, target_idp, target_idp_len);
- goto out;
- }
/* Get target client's entry */
target_client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, NULL);
- if (!target_client) {
+ SILC_ID_GET_ID(id2),
+ TRUE, NULL);
+ if (!target_client)
target_client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
- }
+ SILC_ID_GET_ID(id2),
+ TRUE, NULL);
/* Check whether target client is on the channel */
if (!silc_server_client_on_channel(target_client, channel, &chl)) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+ target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
silc_server_command_send_status_data2(cmd, SILC_COMMAND_KICK,
SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
0, 2, target_idp, target_idp_len,
/* Check that the target client is not channel founder. Channel founder
cannot be kicked from the channel. */
if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
0, 2, tmp, tmp_len);
if (clen > 128)
comment = NULL;
-
/* Send the reply back to the client */
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+ target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_KICK,
SILC_STATUS_OK, 0, ident, 2,
2, tmp, tmp_len,
SILC_NOTIFY_TYPE_KICKED, 3,
target_idp, target_idp_len,
comment, comment ? strlen(comment) : 0,
- idp->data, idp->len);
+ idp->data, silc_buffer_len(idp));
silc_buffer_free(idp);
/* Send KICKED notify to primary route */
SilcBuffer ab =
silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
SilcArgumentPayload args =
- silc_argument_payload_parse(ab->data, ab->len, 1);
+ silc_argument_payload_parse(ab->data, silc_buffer_len(ab), 1);
silc_server_inviteban_process(server, channel->invite_list, 1, args);
silc_buffer_free(ab);
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
unsigned char *username = NULL, *auth;
SilcUInt32 tmp_len;
SilcServerConfigAdmin *admin;
SilcIDListData idata = (SilcIDListData)client;
- bool result = FALSE;
+ SilcBool result = FALSE;
SilcPublicKey cached_key;
+ const char *hostname, *ip;
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+ if (client->data.conn_type != SILC_CONN_CLIENT || !client)
goto out;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
+ silc_socket_stream_get_info(cmd->sock, NULL, &hostname, &ip, NULL);
+
/* Get the username */
username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
if (!username) {
}
/* Get the admin configuration */
- admin = silc_server_config_find_admin(server, cmd->sock->ip,
+ admin = silc_server_config_find_admin(server, (char *)ip,
username, client->nickname);
if (!admin) {
- admin = silc_server_config_find_admin(server, cmd->sock->hostname,
+ admin = silc_server_config_find_admin(server, (char *)hostname,
username, client->nickname);
if (!admin) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
0);
SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
"nickname '%s' from %s", username,
- client->nickname, cmd->sock->hostname));
+ client->nickname, hostname));
goto out;
}
}
admin->passphrase, admin->passphrase_len,
idata->hash, client->id, SILC_ID_CLIENT);
if (!result && admin->publickeys) {
- cached_key = silc_server_get_public_key(server, admin->publickeys);
+ cached_key =
+ silc_server_get_public_key(server,
+ SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
if (!cached_key)
goto out;
result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
QuitInternal q = (QuitInternal)context;
SilcClientID *client_id = (SilcClientID *)q->sock;
SilcClientEntry client;
- SilcSocketConnection sock;
+ SilcPacketStream sock;
client = silc_idlist_find_client_by_id(server->local_list, client_id,
TRUE, NULL);
if (client && client->connection) {
sock = client->connection;
- /* If there is pending outgoing data for the client then purge it
- to the network before closing connection. */
- silc_server_packet_queue_purge(server, sock);
-
/* Close the connection on our side */
client->router = NULL;
client->connection = NULL;
- sock->user_data = NULL;
silc_server_close_connection(server, sock);
}
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
QuitInternal q;
if (server->config->detach_disabled) {
goto out;
}
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+ if (client->data.conn_type != SILC_CONN_CLIENT || !client)
goto out;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
q = silc_calloc(1, sizeof(*q));
q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
- silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
- q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_command_detach_cb,
+ q, 0, 200000);
if (server->config->detach_timeout) {
q = silc_calloc(1, sizeof(*q));
q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
- silc_schedule_task_add(server->schedule, 0,
- silc_server_command_detach_timeout,
- q, server->config->detach_timeout * 60,
- 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_command_detach_timeout,
+ q, server->config->detach_timeout * 60, 0);
}
/* Send reply to the sender */
SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
unsigned char hash[SILC_HASH_MAXLEN], *tmp, *pk, *nick;
SilcClientEntry client;
- SilcClientID *client_id = NULL;
+ SilcID id;
SilcUInt16 old_ident;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
SILC_PACKET_COMMAND, cmd->packet->flags,
- tmpbuf->data, tmpbuf->len, TRUE);
+ tmpbuf->data, silc_buffer_len(tmpbuf));
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_WATCH,
process_watch:
/* Get the client ID */
- tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
- if (!tmp) {
+ if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
0);
goto out;
}
- client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!client_id) {
- silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
- SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
- 0, 2, tmp, tmp_len);
- goto out;
- }
/* Get the client entry which must be in local list */
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, NULL);
+ SILC_ID_GET_ID(id), TRUE, NULL);
if (!client) {
/* Backup checks global list also */
if (server->server_type == SILC_BACKUP_ROUTER)
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
+ SILC_ID_GET_ID(id), TRUE, NULL);
if (!client) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
0, 2, tmp, tmp_len);
pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
while (pk) {
- if (!silc_pkcs_public_key_payload_decode(pk, pk_len, &public_key))
+ if (!silc_public_key_payload_decode(pk, pk_len, &public_key))
continue;
if (type == 0x03)
type = 0x00;
old_ident = silc_command_get_ident(cmd->payload);
silc_command_set_ident(cmd->payload, ++server->cmd_ident);
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
- silc_server_backup_send(server, cmd->sock->user_data, SILC_PACKET_COMMAND,
- cmd->packet->flags, tmpbuf->data, tmpbuf->len,
+ silc_server_backup_send(server, silc_packet_get_context(cmd->sock),
+ SILC_PACKET_COMMAND,
+ cmd->packet->flags, tmpbuf->data,
+ silc_buffer_len(tmpbuf),
FALSE, TRUE);
silc_command_set_ident(cmd->payload, old_ident);
silc_buffer_free(tmpbuf);
}
out:
- silc_free(client_id);
silc_server_command_free(cmd);
}
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
unsigned char *username = NULL, *auth;
SilcUInt32 tmp_len;
SilcServerConfigAdmin *admin;
SilcIDListData idata = (SilcIDListData)client;
- bool result = FALSE;
+ SilcBool result = FALSE;
SilcPublicKey cached_key;
+ const char *hostname, *ip;
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+ if (client->data.conn_type != SILC_CONN_CLIENT || !client)
goto out;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
+ silc_socket_stream_get_info(cmd->sock, NULL, &hostname, &ip, NULL);
+
if (server->server_type != SILC_ROUTER) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
SILC_STATUS_ERR_AUTH_FAILED, 0);
}
/* Get the admin configuration */
- admin = silc_server_config_find_admin(server, cmd->sock->ip,
+ admin = silc_server_config_find_admin(server, (char *)ip,
username, client->nickname);
if (!admin) {
- admin = silc_server_config_find_admin(server, cmd->sock->hostname,
+ admin = silc_server_config_find_admin(server, (char *)hostname,
username, client->nickname);
if (!admin) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
SILC_STATUS_ERR_AUTH_FAILED, 0);
SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
"nickname '%s' from %s", username,
- client->nickname, cmd->sock->hostname));
+ client->nickname, hostname));
goto out;
}
}
admin->passphrase, admin->passphrase_len,
idata->hash, client->id, SILC_ID_CLIENT);
if (!result && admin->publickeys) {
- cached_key = silc_server_get_public_key(server, admin->publickeys);
+ cached_key =
+ silc_server_get_public_key(server,
+ SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
if (!cached_key)
goto out;
result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
SilcBuffer list, tmp2;
SilcChannelEntry channel;
SilcChannelClientEntry chl;
- SilcChannelID *channel_id = NULL;
- unsigned char *id, *tmp, *atype = NULL;
+ SilcID id;
+ unsigned char *tmp_id, *tmp, *atype = NULL;
SilcUInt32 id_len, len, len2;
SilcArgumentPayload args;
SilcHashTableList htl;
SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
SilcBufferStruct blist;
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+ if (client->data.conn_type != SILC_CONN_CLIENT || !client)
goto out;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
/* Get Channel ID */
- id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
- if (id) {
- channel_id = silc_id_payload_parse_id(id, id_len, NULL);
- if (!channel_id) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
- SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
- goto out;
- }
+ if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+ SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
+ goto out;
}
/* Get channel entry. The server must know about the channel since the
client is expected to be on the channel. */
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
- silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
+ tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
+ silc_server_command_send_status_data(
+ cmd, SILC_COMMAND_BAN,
SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
- 0, 2, id, id_len);
+ 0, 2, tmp_id, id_len);
goto out;
}
}
/* Check whether this client is on the channel */
if (!silc_server_client_on_channel(client, channel, &chl)) {
+ tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
- 2, id, id_len);
+ 2, tmp_id, id_len);
goto out;
}
/* The client must be at least channel operator. */
if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
+ tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
- 2, id, id_len);
+ 2, tmp_id, id_len);
goto out;
}
SILC_STR_END);
silc_hash_table_list(channel->ban_list, &htl);
while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
- list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
+ list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2),
type);
silc_hash_table_list_reset(&htl);
}
id, id_len,
atype, 1,
tmp ? blist.data : NULL,
- tmp ? blist.len : 0);
+ tmp ? silc_buffer_len(&blist) : 0);
/* Send to network. */
silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
SILC_STATUS_OK, 0, ident, 2,
2, id, id_len,
3, list ? list->data : NULL,
- list ? list->len : 0);
+ list ? silc_buffer_len(list) : 0);
silc_buffer_free(list);
out:
- silc_free(channel_id);
silc_server_command_free(cmd);
}
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcSocketConnection sock = cmd->sock;
- SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
- SilcChannelID *id = NULL;
+ SilcPacketStream sock = cmd->sock;
+ SilcClientEntry id_entry = silc_packet_get_context(cmd->sock);
+ SilcID id;
SilcChannelEntry channel;
SilcUInt32 len;
unsigned char *tmp;
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
+ if (id_entry->data.conn_type != SILC_CONN_CLIENT || !id_entry)
goto out;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
/* Get Channel ID */
- tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
- if (!tmp) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
- SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
- goto out;
- }
- id = silc_id_payload_parse_id(tmp, len, NULL);
- if (!id) {
+ if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
goto out;
}
/* Get channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
- channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
0, 2, tmp, len);
/* Check whether this client is on the channel */
if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
2, tmp, len);
silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
SILC_BROADCAST(server), channel, id_entry->id);
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
SILC_STATUS_OK, 0, 2, tmp, len);
}
out:
- silc_free(id);
silc_server_command_free(cmd);
}
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
+ SilcIDListData idata = silc_packet_get_context(cmd->sock);
SilcChannelEntry channel;
- SilcChannelID *id = NULL;
+ SilcID id;
SilcBuffer idp;
unsigned char *channel_id;
SilcUInt32 channel_id_len;
/* Check Channel ID */
if (channel_id) {
- id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
- if (!id) {
+ if (!silc_id_payload_parse_id(channel_id, channel_id_len, &id)) {
silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
2, channel_id, channel_id_len);
/* If we are server and we don't know about this channel we will send
the command to our router. If we know about the channel then we also
have the list of users already. */
- if (id)
- channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
+ if (channel_id)
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ SILC_ID_GET_ID(id), NULL);
else
channel = silc_idlist_find_channel_by_name(server->local_list,
channel_namec, NULL);
/* Send USERS command */
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
SILC_PACKET_COMMAND, cmd->packet->flags,
- tmpbuf->data, tmpbuf->len, TRUE);
+ tmpbuf->data, silc_buffer_len(tmpbuf));
/* Reprocess this packet after received reply */
silc_server_command_pending(server, SILC_COMMAND_USERS,
cmd->pending = TRUE;
silc_command_set_ident(cmd->payload, ident);
silc_buffer_free(tmpbuf);
- silc_free(id);
goto out;
}
/* Check the global list as well. */
- if (id)
- channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
+ if (channel_id)
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ SILC_ID_GET_ID(id), NULL);
else
channel = silc_idlist_find_channel_by_name(server->global_list,
channel_namec, NULL);
if (!channel) {
/* Channel really does not exist */
- if (id)
+ if (channel_id)
silc_server_command_send_status_data(
cmd, SILC_COMMAND_USERS,
SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID, 0,
/* If the channel is private or secret do not send anything, unless the
user requesting this command is on the channel or is server */
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
+ if (idata->conn_type == SILC_CONN_CLIENT) {
if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
- && !silc_server_client_on_channel(cmd->sock->user_data, channel,
+ && !silc_server_client_on_channel((SilcClientEntry)idata, channel,
NULL)) {
silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_USERS,
SILC_STATUS_OK, 0, ident, 4,
- 2, idp->data, idp->len,
+ 2, idp->data, silc_buffer_len(idp),
3, lc, 4,
4, client_id_list ?
client_id_list->data : NULL,
client_id_list ?
- client_id_list->len : 0,
+ silc_buffer_len(client_id_list) : 0,
5, client_mode_list ?
client_mode_list->data : NULL,
client_mode_list ?
- client_mode_list->len : 0);
+ silc_buffer_len(client_mode_list) : 0);
silc_buffer_free(idp);
if (client_id_list)
silc_buffer_free(client_id_list);
if (client_mode_list)
silc_buffer_free(client_mode_list);
- silc_free(id);
out:
silc_free(channel_namec);
SilcServer server = cmd->server;
SilcClientEntry client;
SilcServerEntry server_entry;
- SilcClientID *client_id = NULL;
- SilcServerID *server_id = NULL;
+ SilcClientID client_id;
+ SilcServerID server_id;
SilcIDPayload idp = NULL;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
unsigned char *tmp;
id_type = silc_id_payload_get_type(idp);
if (id_type == SILC_ID_CLIENT) {
- client_id = silc_id_payload_get_id(idp);
+ silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
/* If the client is not found from local list there is no chance it
would be locally connected client so send the command further. */
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, NULL);
+ &client_id, TRUE, NULL);
if (!client)
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
+ &client_id, TRUE, NULL);
if ((!client && !cmd->pending && !server->standalone) ||
(client && !client->connection && !cmd->pending &&
(client && !client->data.public_key && !cmd->pending)) {
SilcBuffer tmpbuf;
SilcUInt16 old_ident;
- SilcSocketConnection dest_sock;
+ SilcPacketStream dest_sock;
dest_sock = silc_server_get_client_route(server, NULL, 0,
- client_id, NULL, NULL);
+ &client_id, NULL, NULL);
if (!dest_sock)
goto out;
silc_server_packet_send(server, dest_sock,
SILC_PACKET_COMMAND, cmd->packet->flags,
- tmpbuf->data, tmpbuf->len, TRUE);
+ tmpbuf->data, silc_buffer_len(tmpbuf));
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_GETKEY,
send just OK reply */
public_key = client->data.public_key;
if (public_key)
- pk = silc_pkcs_public_key_payload_encode(public_key);
+ pk = silc_public_key_payload_encode(public_key);
} else if (id_type == SILC_ID_SERVER) {
- server_id = silc_id_payload_get_id(idp);
+ silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
/* If the server is not found from local list there is no chance it
would be locally connected server so send the command further. */
server_entry = silc_idlist_find_server_by_id(server->local_list,
- server_id, TRUE, NULL);
+ &server_id, TRUE, NULL);
if (!server_entry)
server_entry = silc_idlist_find_server_by_id(server->global_list,
- server_id, TRUE, NULL);
+ &server_id, TRUE, NULL);
if (server_entry != server->id_entry &&
((!server_entry && !cmd->pending && !server->standalone) ||
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
SILC_PACKET_COMMAND, cmd->packet->flags,
- tmpbuf->data, tmpbuf->len, TRUE);
+ tmpbuf->data, silc_buffer_len(tmpbuf));
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_GETKEY,
(server_entry == server->id_entry ? server->public_key :
NULL) : server_entry->data.public_key);
if (public_key)
- pk = silc_pkcs_public_key_payload_encode(public_key);
+ pk = silc_public_key_payload_encode(public_key);
} else {
goto out;
}
SILC_STATUS_OK, 0, ident, 2,
2, tmp, tmp_len,
3, pk ? pk->data : NULL,
- pk ? pk->len : 0);
+ pk ? silc_buffer_len(pk) : 0);
out:
if (idp)
silc_id_payload_free(idp);
silc_buffer_free(pk);
- silc_free(client_id);
- silc_free(server_id);
silc_server_command_free(cmd);
}
SilcServer server = cmd->server;
SilcUInt32 tmp_len, auth_len;
unsigned char *service_name, *auth;
- bool send_list = FALSE;
+ SilcBool send_list = FALSE;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SERVICE, cmd, 0, 256);
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
unsigned char *tmp, *host;
SilcUInt32 tmp_len;
SilcUInt32 port = SILC_PORT;
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+ if (client->data.conn_type != SILC_CONN_CLIENT || !client)
goto out;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
SILC_GET32_MSB(port, tmp);
/* Create the connection. It is done with timeout and is async. */
- silc_server_create_connection(server, host, port);
+ silc_server_create_connection(server, FALSE, host, port, NULL, NULL);
/* Send reply to the sender */
silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
SilcServerEntry server_entry;
- SilcSocketConnection sock;
+ SilcPacketStream sock;
unsigned char *tmp;
SilcUInt32 tmp_len;
unsigned char *name;
SilcUInt32 port = SILC_PORT;
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+ if (client->data.conn_type != SILC_CONN_CLIENT || !client)
goto out;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
SILC_STATUS_OK, 0);
/* Close the connection to the server */
- sock = (SilcSocketConnection)server_entry->connection;
+ sock = server_entry->connection;
if (server_entry->server_type == SILC_BACKUP_ROUTER) {
server->backup_closed = TRUE;
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_BANNED_FROM_SERVER,
"Closed by administrator");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
server->backup_noswitch = FALSE;
out:
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+ if (client->data.conn_type != SILC_CONN_CLIENT || !client)
goto out;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
+
/*
servercommand.h
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2005, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Context sent as argument to all commands */
typedef struct {
SilcServer server;
- SilcSocketConnection sock;
+ SilcPacketStream sock;
SilcCommandPayload payload;
SilcArgumentPayload args;
- SilcPacketContext *packet;
+ SilcPacket packet;
int pending; /* Command is being re-processed when TRUE */
int users; /* Reference counter */
} *SilcServerCommandContext;
/* Prototypes */
void silc_server_command_process(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
SilcServerCommandContext silc_server_command_alloc();
void silc_server_command_free(SilcServerCommandContext ctx);
SilcServerCommandContext
silc_server_command_dup(SilcServerCommandContext ctx);
-bool silc_server_command_pending(SilcServer server,
+SilcBool silc_server_command_pending(SilcServer server,
SilcCommand reply_cmd,
SilcUInt16 ident,
SilcCommandCb callback,
void *context);
-bool silc_server_command_pending_timed(SilcServer server,
+SilcBool silc_server_command_pending_timed(SilcServer server,
SilcCommand reply_cmd,
SilcUInt16 ident,
SilcCommandCb callback,
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2005, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Process received command reply. */
void silc_server_command_reply_process(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcBuffer buffer)
{
+ SilcIDListData idata = silc_packet_get_context(sock);
SilcServerCommandReply *cmd;
SilcServerCommandReplyContext ctx;
SilcCommandPayload payload;
SILC_LOG_DEBUG(("Start"));
/* Get command reply payload from packet */
- payload = silc_command_payload_parse(buffer->data, buffer->len);
+ payload = silc_command_payload_parse(buffer->data, silc_buffer_len(buffer));
if (!payload) {
/* Silently ignore bad reply packet */
SILC_LOG_DEBUG(("Bad command reply packet"));
command reply routine receiving it. */
ctx = silc_calloc(1, sizeof(*ctx));
ctx->server = server;
- ctx->sock = silc_socket_dup(sock);
+ ctx->sock = sock;
ctx->payload = payload;
ctx->args = silc_command_get_args(ctx->payload);
ctx->ident = silc_command_get_ident(ctx->payload);
command = silc_command_get(ctx->payload);
+ silc_packet_stream_ref(sock);
/* Client is not allowed to send reply to all commands */
- if (sock->type == SILC_SOCKET_TYPE_CLIENT &&
+ if (idata->conn_type == SILC_CONN_CLIENT &&
command != SILC_COMMAND_WHOIS) {
silc_server_command_reply_free(ctx);
return;
if (cmd) {
silc_command_payload_free(cmd->payload);
if (cmd->sock)
- silc_socket_free(cmd->sock); /* Decrease the reference counter */
+ silc_packet_stream_unref(cmd->sock);
silc_free(cmd->callbacks);
silc_free(cmd);
}
SilcStatus error)
{
SilcServer server = cmd->server;
+ SilcIDListData idata = silc_packet_get_context(cmd->sock);
/* If we received notify for invalid ID we'll remove the ID if we
have it cached. */
if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
- cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ idata->conn_type == SILC_CONN_ROUTER) {
SilcClientEntry client;
- SilcUInt32 tmp_len;
- unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
- if (tmp) {
- SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (client_id) {
- SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
- "the entry from cache"));
- client = silc_idlist_find_client_by_id(server->global_list,
- client_id, FALSE, NULL);
- if (client) {
-
- if (client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- client->data.public_key,
- client);
-
- silc_server_remove_from_channels(server, NULL, client, TRUE,
- NULL, TRUE, FALSE);
- silc_idlist_del_data(client);
- silc_idlist_del_client(server->global_list, client);
- }
- silc_free(client_id);
- }
+ SilcID id;
+ if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id,
+ NULL)) {
+ SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
+ "the entry from cache"));
+ client = silc_idlist_find_client_by_id(server->global_list,
+ SILC_ID_GET_ID(id), FALSE, NULL);
+ if (!client)
+ return;
+
+ if (client->data.public_key)
+ silc_hash_table_del_by_context(server->pk_hash,
+ client->data.public_key,
+ client);
+
+ silc_server_remove_from_channels(server, NULL, client, TRUE,
+ NULL, TRUE, FALSE);
+ silc_idlist_del_data(client);
+ silc_idlist_del_client(server->global_list, client);
}
}
}
{
SilcServer server = cmd->server;
unsigned char *id_data, *umodes;
- char *nickname, *username, *realname, *tmp, *servername = NULL;
+ char *nickname, *username, *realname, *tmp;
unsigned char *fingerprint;
- SilcClientID *client_id;
+ SilcID id;
SilcClientEntry client;
- SilcIDCacheEntry cache = NULL;
char global = FALSE;
- char *nick = NULL;
+ char nick[128 + 1], servername[256 + 1], uname[128 + 1];
SilcUInt32 mode = 0, len, len2, id_len, flen;
+ const char *hostname, *ip;
+
+ silc_socket_stream_get_info(cmd->sock, NULL, &hostname, &ip, NULL);
id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
if (tmp)
SILC_GET32_MSB(mode, tmp);
- client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
- if (!client_id)
+ if (!silc_id_payload_parse_id(id_data, id_len, &id))
return FALSE;
fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
/* Check if we have this client cached already. */
- client = silc_idlist_find_client_by_id(server->local_list, client_id,
+ client = silc_idlist_find_client_by_id(server->local_list,
+ SILC_ID_GET_ID(id),
FALSE, NULL);
if (!client) {
- client = silc_idlist_find_client_by_id(server->global_list, client_id,
+ client = silc_idlist_find_client_by_id(server->global_list,
+ SILC_ID_GET_ID(id),
FALSE, NULL);
global = TRUE;
}
return FALSE;
/* Take hostname out of nick string if it includes it. */
- silc_parse_userfqdn(nickname, &nick, &servername);
+ silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
+ sizeof(servername));
/* We don't have that client anywhere, add it. The client is added
to global list since server didn't have it in the lists so it must be
global. This will check for valid nickname and username strings. */
- client = silc_idlist_add_client(server->global_list, nick, username,
- strdup(realname), client_id,
- cmd->sock->user_data, NULL, 0);
+ client = silc_idlist_add_client(server->global_list,
+ strdup(nick), username,
+ strdup(realname),
+ silc_id_dup(SILC_ID_GET_ID(id),
+ SILC_ID_CLIENT),
+ silc_packet_get_context(cmd->sock),
+ NULL);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
- silc_free(nick);
- silc_free(servername);
return FALSE;
}
(SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
client->mode = mode;
- client->servername = servername;
+ client->servername = servername[0] ? strdup(servername) : NULL;
} else {
/* We have the client already, update the data */
SILC_LOG_DEBUG(("Updating client data"));
/* Check nickname */
- silc_parse_userfqdn(nickname, &nick, &servername);
+ silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
+ sizeof(servername));
nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
128, NULL);
if (!nickname) {
SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOIS reply "
"from %s",
- cmd->sock->hostname ? cmd->sock->hostname : "", nick));
- silc_free(nick);
- silc_free(servername);
+ hostname ? hostname : "", nick));
return FALSE;
}
/* Check username */
- silc_parse_userfqdn(username, &tmp, NULL);
- if (!silc_identifier_verify(tmp, strlen(tmp), SILC_STRING_UTF8, 128)) {
- silc_free(tmp);
- silc_free(nick);
- silc_free(servername);
+ silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
+ if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128)) {
SILC_LOG_ERROR(("Malformed username '%s' received in WHOIS reply "
"from %s",
- cmd->sock->hostname ? cmd->sock->hostname : "", tmp));
+ hostname ? hostname : "", tmp));
return FALSE;
}
- silc_free(tmp);
/* Remove the old cache entry */
silc_idcache_del_by_context(global ? server->global_list->clients :
- server->local_list->clients, client);
+ server->local_list->clients, client, NULL);
silc_free(client->nickname);
silc_free(client->username);
silc_free(client->userinfo);
silc_free(client->servername);
- client->nickname = nick;
+ client->nickname = strdup(nick);
client->username = strdup(username);
client->userinfo = strdup(realname);
- client->servername = servername;
+ client->servername = servername[0] ? strdup(servername) : NULL;
client->mode = mode;
client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
/* Create new cache entry */
silc_idcache_add(global ? server->global_list->clients :
server->local_list->clients, nickname, client->id,
- client, 0, NULL);
- silc_free(client_id);
+ client);
}
/* Save channel list if it was sent to us */
} else {
silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
}
-
- /* If client is global and is not on any channel then add that we'll
- expire the entry after a while. */
- if (global) {
- silc_idlist_find_client_by_id(server->global_list, client->id,
- FALSE, &cache);
- if (!silc_hash_table_count(client->channels))
- cache->expire = time(NULL) + 300;
- else
- cache->expire = 0;
- }
}
if (fingerprint && flen == sizeof(client->data.fingerprint))
}
/* Save the public key. */
- if (!silc_pkcs_public_key_decode(pk.data, pk.data_len,
- &client->data.public_key)) {
+ if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC,
+ pk.data, pk.data_len,
+ &client->data.public_key)) {
silc_free(pk.type);
silc_free(pk.data);
continue;
{
unsigned char *tmp;
SilcUInt32 len;
- SilcClientEntry client = cmd->sock->user_data;
+ SilcClientEntry client = silc_packet_get_context(cmd->sock);
/* Take Requested Attributes if set. */
tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
SILC_SERVER_CMD_REPLY_FUNC(whois)
{
SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
+ SilcIDListData idata = silc_packet_get_context(cmd->sock);
SilcStatus status, error;
COMMAND_CHECK_STATUS;
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) {
+ if (idata->conn_type != SILC_CONN_CLIENT) {
if (!silc_server_command_reply_whois_save(cmd))
goto out;
} else {
SilcServer server = cmd->server;
SilcUInt32 len, id_len;
unsigned char *id_data;
- char *nickname, *username, *realname, *servername = NULL, *tmp;
- SilcClientID *client_id;
+ char *nickname, *username, *realname;
+ SilcID id;
SilcClientEntry client;
SilcIDCacheEntry cache = NULL;
- char *nick = NULL;
+ char nick[128 + 1], servername[256 + 1], uname[128 + 1];
int global = FALSE;
+ const char *hostname, *ip;
+
+ silc_socket_stream_get_info(cmd->sock, NULL, &hostname, &ip, NULL);
id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
realname = silc_argument_get_arg_type(cmd->args, 5, &len);
- client_id = silc_id_payload_parse_id(id_data, id_len, NULL);
- if (!client_id)
+ if (!silc_id_payload_parse_id(id_data, id_len, &id))
return FALSE;
/* Check if we have this client cached already. */
- client = silc_idlist_find_client_by_id(server->local_list, client_id,
+ client = silc_idlist_find_client_by_id(server->local_list,
+ SILC_ID_GET_ID(id),
FALSE, &cache);
if (!client) {
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, FALSE, &cache);
+ SILC_ID_GET_ID(id),
+ FALSE, &cache);
global = TRUE;
}
return FALSE;
/* Take hostname out of nick string if it includes it. */
- silc_parse_userfqdn(nickname, &nick, &servername);
+ silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
+ sizeof(servername));
/* We don't have that client anywhere, add it. The client is added
to global list since server didn't have it in the lists so it must be
global. */
- client = silc_idlist_add_client(server->global_list, nick, username,
+ client = silc_idlist_add_client(server->global_list,
+ strdup(nick), username,
strdup(realname),
- silc_id_dup(client_id, SILC_ID_CLIENT),
- cmd->sock->user_data, NULL,
- SILC_ID_CACHE_EXPIRE_DEF);
+ silc_id_dup(SILC_ID_GET_ID(id),
+ SILC_ID_CLIENT),
+ silc_packet_get_context(cmd->sock), NULL);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
- silc_free(nick);
- silc_free(servername);
return FALSE;
}
client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
- client->servername = servername;
+ client->servername = servername[0] ? strdup(servername) : NULL;
} else {
/* We have the client already, update the data */
/* Check nickname */
- silc_parse_userfqdn(nickname, &nick, &servername);
+ silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
+ sizeof(servername));
nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
128, NULL);
if (!nickname) {
SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOWAS reply "
"from %s",
- cmd->sock->hostname ? cmd->sock->hostname : "", nick));
- silc_free(nick);
- silc_free(servername);
+ hostname ? hostname : "", nick));
return FALSE;
}
/* Check username */
- silc_parse_userfqdn(username, &tmp, NULL);
- if (!silc_identifier_verify(tmp, strlen(tmp), SILC_STRING_UTF8, 128)) {
- silc_free(tmp);
- silc_free(nick);
- silc_free(servername);
- SILC_LOG_ERROR(("Malformed username '%s' received in WHOWAS reply "
- "from %s",
- cmd->sock->hostname ? cmd->sock->hostname : "", tmp));
+ silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
+ if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128))
return FALSE;
- }
- silc_free(tmp);
silc_free(client->nickname);
silc_free(client->username);
silc_free(client->servername);
- client->nickname = nick;
+ client->nickname = strdup(nick);
client->username = strdup(username);
- client->servername = servername;
+ client->servername = servername[0] ? strdup(servername) : NULL;
client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
/* Remove the old cache entry and create a new one */
silc_idcache_del_by_context(global ? server->global_list->clients :
- server->local_list->clients, client);
+ server->local_list->clients, client, NULL);
silc_idcache_add(global ? server->global_list->clients :
server->local_list->clients, nickname, client->id,
- client, 0, NULL);
+ client);
}
- /* If client is global and is not on any channel then add that we'll
- expire the entry after a while. */
- if (global) {
- silc_idlist_find_client_by_id(server->global_list, client->id,
- FALSE, &cache);
- if (!silc_hash_table_count(client->channels))
- cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
- else
- cache->expire = 0;
- }
-
- silc_free(client_id);
-
return TRUE;
}
SilcUInt32 len, id_len;
unsigned char *id_data;
char *name, *info;
- SilcClientID *client_id = NULL;
- SilcServerID *server_id = NULL;
- SilcChannelID *channel_id = NULL;
+ SilcClientID client_id;
+ SilcServerID server_id;
+ SilcChannelID*channel_id;
SilcClientEntry client;
SilcServerEntry server_entry;
SilcChannelEntry channel;
char global = FALSE;
- char *nick = NULL;
+ char nick[128 + 1];
SilcIDPayload idp = NULL;
SilcIdType id_type;
- int expire = 0;
id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
if (!id_data)
switch (id_type) {
case SILC_ID_CLIENT:
- client_id = silc_id_payload_get_id(idp);
- if (!client_id)
+ if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
goto error;
SILC_LOG_DEBUG(("Received client information"));
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, FALSE, NULL);
+ &client_id, FALSE, NULL);
if (!client) {
- client = silc_idlist_find_client_by_id(server->global_list, client_id,
+ client = silc_idlist_find_client_by_id(server->global_list, &client_id,
FALSE, NULL);
global = TRUE;
}
/* Take nickname */
if (name)
- silc_parse_userfqdn(name, &nick, NULL);
+ silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
/* We don't have that client anywhere, add it. The client is added
to global list since server didn't have it in the lists so it must be
global. */
- client = silc_idlist_add_client(server->global_list, nick, info, NULL,
- client_id, cmd->sock->user_data,
- NULL, time(NULL) + 300);
+ client = silc_idlist_add_client(server->global_list,
+ nick[0] ? nick : NULL, info, NULL,
+ silc_id_dup(&client_id, SILC_ID_CLIENT),
+ silc_packet_get_context(cmd->sock),
+ NULL);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
- silc_free(nick);
goto error;
}
/* Take nickname */
if (name) {
- silc_parse_userfqdn(name, &nick, NULL);
+ silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
/* Check nickname */
name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
128, NULL);
if (!name) {
- SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY reply "
- "from %s",
- cmd->sock->hostname ?
- cmd->sock->hostname : "", nick));
+ SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY "
+ "reply ", nick));
return FALSE;
}
/* Remove the old cache entry */
silc_idcache_del_by_context(global ? server->global_list->clients :
- server->local_list->clients, client);
+ server->local_list->clients, client, NULL);
silc_free(client->nickname);
- client->nickname = nick;
+ client->nickname = strdup(nick);
/* Add new cache entry */
silc_idcache_add(global ? server->global_list->clients :
server->local_list->clients, name, client->id,
- client, expire, NULL);
+ client);
}
if (info) {
client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
-
- /* If client is global and is not on any channel then add that we'll
- expire the entry after a while. */
- if (global && server->server_type == SILC_SERVER) {
- SilcIDCacheEntry cache = NULL;
- silc_idlist_find_client_by_id(server->global_list, client->id,
- FALSE, &cache);
- if (!silc_hash_table_count(client->channels))
- cache->expire = time(NULL) + 300;
- else
- cache->expire = 0;
- }
-
- silc_free(client_id);
}
break;
if (!name)
goto error;
- server_id = silc_id_payload_get_id(idp);
- if (!server_id)
+ if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
goto error;
SILC_LOG_DEBUG(("Received server information"));
server_entry = silc_idlist_find_server_by_id(server->local_list,
- server_id, FALSE, NULL);
+ &server_id, FALSE, NULL);
if (!server_entry)
server_entry = silc_idlist_find_server_by_id(server->global_list,
- server_id, FALSE, NULL);
+ &server_id, FALSE, NULL);
if (!server_entry) {
/* If router did not find such Server ID in its lists then this must
be bogus server or some router in the net is buggy. */
/* We don't have that server anywhere, add it. */
server_entry = silc_idlist_add_server(server->global_list,
strdup(name), 0,
- server_id, server->router,
+ silc_id_dup(&server_id,
+ SILC_ID_SERVER),
+ server->router,
SILC_PRIMARY_ROUTE(server));
- if (!server_entry) {
- silc_free(server_id);
+ if (!server_entry)
goto error;
- }
+
server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
- server_id = NULL;
}
- silc_free(server_id);
break;
case SILC_ID_CHANNEL:
if (!name)
goto error;
- channel_id = silc_id_payload_get_id(idp);
- if (!channel_id)
+ if (!silc_id_payload_get_id(idp, &channel_id, sizeof(channel_id)))
goto error;
SILC_LOG_DEBUG(("Received channel information"));
/* We don't have that channel anywhere, add it. */
channel = silc_idlist_add_channel(server->global_list, strdup(name),
- SILC_CHANNEL_MODE_NONE, channel_id,
+ SILC_CHANNEL_MODE_NONE,
+ silc_id_dup(&channel_id,
+ SILC_ID_CHANNEL),
server->router, NULL, NULL, 0);
if (!channel) {
- silc_free(channel_id);
silc_free(info);
goto error;
}
silc_free(info);
- channel_id = NULL;
}
- silc_free(channel_id);
break;
}
SilcServer server = cmd->server;
SilcStatus status, error;
SilcServerEntry entry;
- SilcServerID *server_id;
+ SilcID id;
SilcUInt32 tmp_len;
unsigned char *tmp, *name;
COMMAND_CHECK_STATUS;
/* Get Server ID */
- tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
- if (!tmp)
- goto out;
- server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!server_id)
+ if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* Get the name */
if (!name)
goto out;
- entry = silc_idlist_find_server_by_id(server->local_list, server_id,
+ entry = silc_idlist_find_server_by_id(server->local_list,
+ SILC_ID_GET_ID(id),
FALSE, NULL);
if (!entry) {
- entry = silc_idlist_find_server_by_id(server->global_list, server_id,
+ entry = silc_idlist_find_server_by_id(server->global_list,
+ SILC_ID_GET_ID(id),
FALSE, NULL);
if (!entry) {
/* Add the server to global list */
- server_id = silc_id_dup(server_id, SILC_ID_SERVER);
entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
- server_id, cmd->sock->user_data,
+ silc_id_dup(SILC_ID_GET_ID(id),
+ SILC_ID_SERVER),
+ silc_packet_get_context(cmd->sock),
cmd->sock);
- if (!entry) {
- silc_free(server_id);
+ if (!entry)
goto out;
- }
+
entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
}
}
SilcServer server = cmd->server;
SilcStatus status, error;
SilcServerEntry entry = NULL;
- SilcServerID *server_id;
+ SilcID id;
SilcUInt32 tmp_len;
unsigned char *tmp;
COMMAND_CHECK_STATUS;
/* Get Server ID */
- tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
- if (!tmp)
- goto out;
- server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!server_id)
+ if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
goto out;
- entry = silc_idlist_find_server_by_id(server->local_list, server_id,
+ entry = silc_idlist_find_server_by_id(server->local_list,
+ SILC_ID_GET_ID(id),
TRUE, NULL);
if (!entry) {
- entry = silc_idlist_find_server_by_id(server->global_list, server_id,
+ entry = silc_idlist_find_server_by_id(server->global_list,
+ SILC_ID_GET_ID(id),
TRUE, NULL);
if (!entry) {
SilcBuffer buffer;
/* entry isn't known so we IDENTIFY it. otherwise the
silc_server_command_motd won't know about it and tell
the client that there is no such server */
+ tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
++server->cmd_ident, 5,
1, NULL, 0, 2, NULL, 0,
5, tmp, tmp_len);
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
SILC_PACKET_COMMAND, 0, buffer->data,
- buffer->len, TRUE);
+ silc_buffer_len(buffer));
silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
server->cmd_ident,
silc_server_command_reply_motd,
SilcServer server = cmd->server;
SilcIDCacheEntry cache = NULL;
SilcStatus status, error;
- SilcChannelID *id;
- SilcClientID *client_id = NULL;
+ SilcID id, id2;
SilcChannelEntry entry;
SilcHmac hmac = NULL;
- SilcUInt32 id_len, len, list_count;
- unsigned char *id_string;
+ SilcUInt32 len, list_count;
char *channel_name, *channel_namec = NULL, *tmp;
SilcUInt32 mode, created;
SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
goto out;
/* Get channel ID */
- id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
- if (!id_string)
+ if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* Get client ID */
- tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
- if (!tmp)
- goto out;
- client_id = silc_id_payload_parse_id(tmp, len, NULL);
- if (!client_id)
+ if (!silc_argument_get_decoded(cmd->args, 4, SILC_ARGUMENT_ID, &id2, NULL))
goto out;
/* Get mode mask */
tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
if (tmp) {
keyp = silc_buffer_alloc(len);
- silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
+ silc_buffer_pull_tail(keyp, silc_buffer_truelen(keyp));
silc_buffer_put(keyp, tmp, len);
}
- /* Parse the Channel ID */
- id = silc_id_payload_parse_id(id_string, id_len, NULL);
- if (!id)
- goto out;
-
/* Get hmac */
tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
if (tmp) {
/* Get founder key */
tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
if (tmp)
- silc_pkcs_public_key_payload_decode(tmp, len, &founder_key);
+ silc_public_key_payload_decode(tmp, len, &founder_key);
/* See whether we already have the channel. */
channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
(created == 0 ? "existing" : "created"), channel_name,
- silc_id_render(id, SILC_ID_CHANNEL)));
+ silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL)));
/* If the channel is found from global list we must move it to the
local list. */
/* Add the channel to our local list. */
entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
- SILC_CHANNEL_MODE_NONE, id,
- server->router, NULL, hmac, 0);
- if (!entry) {
- silc_free(id);
+ SILC_CHANNEL_MODE_NONE,
+ silc_id_dup(SILC_ID_GET_ID(id),
+ SILC_ID_CHANNEL),
+ server->router, NULL, NULL, hmac);
+ if (!entry)
goto out;
- }
+
hmac = NULL;
server->stat.my_channels++;
server->stat.channels++;
/* The entry exists. */
/* If ID has changed, then update it to the cache too. */
- if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
- silc_idlist_replace_channel_id(server->local_list, entry->id, id);
+ if (!SILC_ID_CHANNEL_COMPARE(entry->id, SILC_ID_GET_ID(id)))
+ silc_idlist_replace_channel_id(server->local_list, entry->id,
+ SILC_ID_GET_ID(id));
entry->disabled = FALSE;
entry->global_users = (created == 0 ? TRUE : FALSE);
/* If channel was just created the mask must be zero */
- if (!entry->global_users && mode) {
- SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
- "new channel, forcing it to zero", cmd->sock->hostname));
+ if (!entry->global_users && mode)
mode = 0;
- }
/* Save channel mode */
entry->mode = mode;
/* Save the users to the channel */
silc_server_save_users_on_channel(server, cmd->sock, entry,
- client_id, client_id_list,
+ SILC_ID_GET_ID(id2), client_id_list,
client_mode_list, list_count);
entry->users_resolved = TRUE;
silc_free(channel_namec);
if (hmac)
silc_hmac_free(hmac);
- silc_free(client_id);
silc_server_command_reply_free(cmd);
silc_pkcs_public_key_free(founder_key);
SilcServer server = cmd->server;
SilcStatus status, error;
SilcChannelEntry channel;
- SilcChannelID *channel_id = NULL;
+ SilcID id;
SilcBuffer client_id_list;
SilcBuffer client_mode_list;
unsigned char *tmp;
COMMAND_CHECK_STATUS;
/* Get channel ID */
- tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
- if (!tmp)
- goto out;
- channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!channel_id)
+ if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
SilcBuffer idp;
if (server->server_type != SILC_SERVER)
goto out;
- idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
+ idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
- 1, 5, idp->data, idp->len);
+ 1, 5, idp->data, silc_buffer_len(idp));
silc_buffer_free(idp);
/* Register pending command callback. After we've received the channel
out:
SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
- silc_free(channel_id);
err:
silc_server_command_reply_free(cmd);
}
SilcStatus status, error;
SilcClientEntry client = NULL;
SilcServerEntry server_entry = NULL;
- SilcClientID *client_id = NULL;
- SilcServerID *server_id = NULL;
+ SilcClientID client_id;
+ SilcServerID server_id;
unsigned char *tmp;
SilcUInt32 len;
SilcIDPayload idp = NULL;
goto out;
/* Decode the public key payload */
- if (!silc_pkcs_public_key_payload_decode(tmp, len, &public_key))
+ if (!silc_public_key_payload_decode(tmp, len, &public_key))
goto out;
id_type = silc_id_payload_get_type(idp);
if (id_type == SILC_ID_CLIENT) {
- client_id = silc_id_payload_get_id(idp);
+ silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
- client = silc_idlist_find_client_by_id(server->local_list, client_id,
+ client = silc_idlist_find_client_by_id(server->local_list, &client_id,
TRUE, NULL);
if (!client) {
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
+ &client_id, TRUE, NULL);
if (!client)
goto out;
}
public_key = NULL;
}
} else if (id_type == SILC_ID_SERVER) {
- server_id = silc_id_payload_get_id(idp);
+ silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
- server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
- TRUE, NULL);
+ server_entry = silc_idlist_find_server_by_id(server->local_list,
+ &server_id, TRUE, NULL);
if (!server_entry) {
server_entry = silc_idlist_find_server_by_id(server->global_list,
- server_id, TRUE, NULL);
+ &server_id, TRUE, NULL);
if (!server_entry)
goto out;
}
SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
if (idp)
silc_id_payload_free(idp);
- silc_free(client_id);
- silc_free(server_id);
if (public_key)
silc_pkcs_public_key_free(public_key);
err:
SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
SilcServer server = cmd->server;
SilcStatus status, error;
- SilcChannelID *channel_id = NULL;
+ SilcID id;
SilcChannelEntry channel;
SilcIDCacheEntry cache;
- SilcUInt32 len;
unsigned char *tmp, *name, *namec = NULL, *topic;
SilcUInt32 usercount = 0;
- bool global_list = FALSE;
+ SilcBool global_list = FALSE;
COMMAND_CHECK_STATUS;
- tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
- if (!tmp)
- goto out;
- channel_id = silc_id_payload_parse_id(tmp, len, NULL);
- if (!channel_id)
+ if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
goto out;
name = silc_argument_get_arg_type(cmd->args, 3, NULL);
goto out;
channel = silc_idlist_add_channel(server->global_list, strdup(name),
- SILC_CHANNEL_MODE_NONE, channel_id,
- server->router, NULL, NULL,
- time(NULL) + 60);
+ SILC_CHANNEL_MODE_NONE,
+ silc_id_dup(SILC_ID_GET_ID(id),
+ SILC_ID_CHANNEL),
+ server->router, NULL, NULL, NULL);
if (!channel)
goto out;
- channel_id = NULL;
- } else {
- /* Found, update expiry */
- if (global_list && server->server_type == SILC_SERVER)
- cache->expire = time(NULL) + 60;
}
channel->user_count = usercount;
return;
}
- /* Now purge all old entries from the global list, otherwise we'll might
- have non-existent entries for long periods of time in the cache. */
- silc_idcache_purge(server->global_list->channels);
-
out:
SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
- silc_free(channel_id);
err:
silc_free(namec);
silc_server_command_reply_free(cmd);
/* Context sent as argument to all command reply functions */
typedef struct {
SilcServer server;
- SilcSocketConnection sock;
+ SilcPacketStream sock;
SilcCommandPayload payload;
SilcArgumentPayload args;
/* Prototypes */
void silc_server_command_reply_free(SilcServerCommandReplyContext cmd);
void silc_server_command_reply_process(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcBuffer buffer);
SILC_SERVER_CMD_REPLY_FUNC(whois);
SILC_SERVER_CMD_REPLY_FUNC(whowas);
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2005, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
void silc_idlist_add_data(void *entry, SilcIDListData idata)
{
- SilcIDListData data = (SilcIDListData)entry;
- data->send_key = idata->send_key;
- data->receive_key = idata->receive_key;
- data->hmac_send = idata->hmac_send;
- data->hmac_receive = idata->hmac_receive;
- data->psn_send = idata->psn_send;
- data->psn_receive = idata->psn_receive;
+ SilcIDListData data = entry;
data->hash = idata->hash;
data->public_key = idata->public_key;
memcpy(data->fingerprint, idata->fingerprint, sizeof(data->fingerprint));
data->last_receive = idata->last_receive;
data->last_sent = idata->last_sent;
data->status = idata->status;
-
data->created = time(0); /* Update creation time */
}
void silc_idlist_del_data(void *entry)
{
SilcIDListData idata = (SilcIDListData)entry;
- if (idata->send_key)
- silc_cipher_free(idata->send_key);
- if (idata->receive_key)
- silc_cipher_free(idata->receive_key);
- if (idata->rekey) {
- if (idata->rekey->send_enc_key) {
- memset(idata->rekey->send_enc_key, 0, idata->rekey->enc_key_len);
- silc_free(idata->rekey->send_enc_key);
- }
- silc_free(idata->rekey);
- }
- if (idata->hmac_send)
- silc_hmac_free(idata->hmac_send);
- if (idata->hmac_receive)
- silc_hmac_free(idata->hmac_receive);
+
if (idata->hash)
silc_hash_free(idata->hash);
if (idata->public_key)
silc_pkcs_public_key_free(idata->public_key);
- idata->send_key = NULL;
- idata->receive_key = NULL;
- idata->rekey = NULL;
- idata->hmac_send = NULL;
- idata->hmac_receive = NULL;
idata->hash = NULL;
idata->public_key = NULL;
}
/* Purges ID cache */
-SILC_TASK_CALLBACK_GLOBAL(silc_idlist_purge)
+SILC_TASK_CALLBACK(silc_idlist_purge)
{
SilcServer server = app_context;
SilcIDListPurge i = (SilcIDListPurge)context;
SILC_LOG_DEBUG(("Purging cache"));
+#if 0
+ /* XXX */
silc_idcache_purge(i->cache);
- silc_schedule_task_add(server->schedule, 0, silc_idlist_purge,
- (void *)i, i->timeout, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+ silc_schedule_task_add_timeout(server->schedule, silc_idlist_purge, i,
+ i->timeout, 0);
+#endif
}
/******************************************************************************
server->connection = connection;
if (!silc_idcache_add(id_list->servers, server_namec,
- (void *)server->id, (void *)server, 0, NULL)) {
+ (void *)server->id, (void *)server)) {
silc_free(server);
silc_free(server_namec);
return NULL;
SilcServerEntry
silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id,
- bool registered, SilcIDCacheEntry *ret_entry)
+ SilcBool registered, SilcIDCacheEntry *ret_entry)
{
SilcIDCacheEntry id_cache = NULL;
SilcServerEntry server;
SILC_LOG_DEBUG(("Server ID (%s)",
silc_id_render(id, SILC_ID_SERVER)));
- if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id,
- &id_cache))
+ if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id, &id_cache))
return NULL;
server = (SilcServerEntry)id_cache->context;
SilcServerEntry
silc_idlist_find_server_by_name(SilcIDList id_list, char *name,
- bool registered, SilcIDCacheEntry *ret_entry)
+ SilcBool registered, SilcIDCacheEntry *ret_entry)
{
SilcIDCacheEntry id_cache = NULL;
SilcServerEntry server;
SilcServerEntry
silc_idlist_find_server_by_conn(SilcIDList id_list, char *hostname,
- int port, bool registered,
+ int port, SilcBool registered,
SilcIDCacheEntry *ret_entry)
{
- SilcIDCacheList list = NULL;
+ SilcList list;
SilcIDCacheEntry id_cache = NULL;
SilcServerEntry server = NULL;
- SilcSocketConnection sock;
+ SilcPacketStream sock;
+ const char *host = NULL, *ip = NULL;
SILC_LOG_DEBUG(("Server by hostname %s and port %d", hostname, port));
if (!silc_idcache_get_all(id_list->servers, &list))
return NULL;
- if (!silc_idcache_list_first(list, &id_cache)) {
- silc_idcache_list_free(list);
- return NULL;
- }
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ server = id_cache->context;
+ sock = server->connection;
- while (id_cache) {
- server = (SilcServerEntry)id_cache->context;
- sock = (SilcSocketConnection)server->connection;
-
- if (sock && ((sock->hostname && !strcasecmp(sock->hostname, hostname)) ||
- (sock->ip && !strcasecmp(sock->ip, hostname)))
- && server->id->port == SILC_SWAB_16(port))
- break;
+ if (sock && silc_socket_stream_get_info(sock, NULL, &host, &ip, NULL)) {
+ if (((host && !strcasecmp(host, hostname)) ||
+ (ip && !strcasecmp(ip, hostname))) &&
+ server->id->port == SILC_SWAB_16(port))
+ break;
+ }
id_cache = NULL;
server = NULL;
-
- if (!silc_idcache_list_next(list, &id_cache))
- break;
}
- silc_idcache_list_free(list);
-
if (server && registered &&
!(server->data.status & SILC_IDLIST_STATUS_REGISTERED))
return NULL;
SILC_LOG_DEBUG(("Replacing Server ID"));
- if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id,
- &id_cache))
+ if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id, &id_cache))
return NULL;
server = (SilcServerEntry)id_cache->context;
/* Remove the old entry and add a new one */
- silc_idcache_del_by_id(id_list->servers, (void *)server->id);
-
- silc_free(server->id);
- server->id = new_id;
-
- silc_idcache_add(id_list->servers, name, server->id, server, 0, NULL);
+ silc_idcache_del_by_id(id_list->servers, (void *)server->id, NULL);
+ *server->id = *new_id;
+ silc_idcache_add(id_list->servers, name, server->id, server);
SILC_LOG_DEBUG(("Found"));
{
if (entry) {
/* Remove from cache */
- if (!silc_idcache_del_by_context(id_list->servers, entry)) {
+ if (!silc_idcache_del_by_context(id_list->servers, entry, NULL)) {
SILC_LOG_DEBUG(("Unknown server, did not delete"));
return FALSE;
}
SilcClientEntry
silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
char *userinfo, SilcClientID *id,
- SilcServerEntry router, void *connection,
- int expire)
+ SilcServerEntry router, void *connection)
{
SilcClientEntry client;
char *nicknamec = NULL;
/* Check username. */
if (username) {
- char *u = NULL, *h = NULL;
- silc_parse_userfqdn(username, &u, &h);
+ char u[128 + 1], h[256 + 1];
+ int ret;
+
+ ret = silc_parse_userfqdn(username, u, sizeof(u), h, sizeof(h));
if (!u)
return NULL;
- if (!silc_identifier_verify(u, strlen(u), SILC_STRING_UTF8, 128)) {
- silc_free(u);
- silc_free(h);
+ if (!silc_identifier_verify(u, strlen(u), SILC_STRING_UTF8, 128))
return NULL;
- }
- if (h && !silc_identifier_verify(h, strlen(h), SILC_STRING_UTF8, 256)) {
- silc_free(u);
- silc_free(h);
+ if (ret > 1 && !silc_identifier_verify(h, strlen(h),
+ SILC_STRING_UTF8, 256))
return NULL;
- }
}
client = silc_calloc(1, sizeof(*client));
NULL, NULL, NULL, NULL, TRUE);
if (!silc_idcache_add(id_list->clients, nicknamec, (void *)client->id,
- (void *)client, expire, NULL)) {
+ (void *)client)) {
silc_hash_table_free(client->channels);
silc_free(client);
silc_free(nicknamec);
SILC_LOG_DEBUG(("Start"));
if (entry) {
- if (!silc_idcache_del_by_context(id_list->clients, entry)) {
+ if (!silc_idcache_del_by_context(id_list->clients, entry, NULL /* XXX */)) {
SILC_LOG_DEBUG(("Unknown client, did not delete"));
return FALSE;
}
void silc_idlist_client_destructor(SilcIDCache cache,
SilcIDCacheEntry entry,
- void *context)
+ void *dest_context,
+ void *app_context)
{
- SilcServer server = context;
+ SilcServer server = app_context;
SilcClientEntry client;
client = (SilcClientEntry)entry->context;
SilcClientEntry **clients,
SilcUInt32 *clients_count)
{
- SilcIDCacheList list = NULL;
+ SilcList list;
SilcIDCacheEntry id_cache = NULL;
SILC_LOG_DEBUG(("Start"));
return FALSE;
*clients = silc_realloc(*clients,
- (silc_idcache_list_count(list) + *clients_count) *
+ (silc_list_count(list) + *clients_count) *
sizeof(**clients));
- silc_idcache_list_first(list, &id_cache);
- (*clients)[(*clients_count)++] = (SilcClientEntry)id_cache->context;
-
- while (silc_idcache_list_next(list, &id_cache))
- (*clients)[(*clients_count)++] = (SilcClientEntry)id_cache->context;
- silc_idcache_list_free(list);
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list)))
+ (*clients)[(*clients_count)++] = id_cache->context;
SILC_LOG_DEBUG(("Found total %d clients", *clients_count));
SilcClientEntry **clients,
SilcUInt32 *clients_count)
{
- SilcIDCacheList list = NULL;
+ SilcList list;
SilcIDCacheEntry id_cache = NULL;
unsigned char hash[SILC_HASH_MAXLEN];
SilcClientID client_id;
return FALSE;
*clients = silc_realloc(*clients,
- (silc_idcache_list_count(list) + *clients_count) *
+ (silc_list_count(list) + *clients_count) *
sizeof(**clients));
- silc_idcache_list_first(list, &id_cache);
- (*clients)[(*clients_count)++] = (SilcClientEntry)id_cache->context;
-
- while (silc_idcache_list_next(list, &id_cache))
- (*clients)[(*clients_count)++] = (SilcClientEntry)id_cache->context;
-
- silc_idcache_list_free(list);
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list)))
+ (*clients)[(*clients_count)++] = id_cache->context;
SILC_LOG_DEBUG(("Found total %d clients", *clients_count));
SilcClientEntry
silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
- bool registered, SilcIDCacheEntry *ret_entry)
+ SilcBool registered, SilcIDCacheEntry *ret_entry)
{
SilcIDCacheEntry id_cache = NULL;
SilcClientEntry client;
SILC_LOG_DEBUG(("Client ID (%s)",
silc_id_render(id, SILC_ID_CLIENT)));
- /* Do extended search since the normal ID comparison function for
- Client ID's compares only the hash from the Client ID and not the
- entire ID. The silc_hash_client_id_compare compares the entire
- Client ID as we want to find one specific Client ID. */
- if (!silc_idcache_find_by_id_one_ext(id_list->clients, (void *)id,
- NULL, NULL,
- silc_hash_client_id_compare, NULL,
- &id_cache))
+ /* Find the exact client with the exact Client ID */
+ if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id, &id_cache))
return NULL;
client = (SilcClientEntry)id_cache->context;
return NULL;
}
- /* Do extended search since the normal ID comparison function for
- Client ID's compares only the hash from the Client ID and not the
- entire ID. The silc_hash_client_id_compare compares the entire
- Client ID as we want to find one specific Client ID. */
- if (!silc_idcache_find_by_id_one_ext(id_list->clients, (void *)old_id,
- NULL, NULL,
- silc_hash_client_id_compare, NULL,
- &id_cache))
+ /* Find exact client with exact Client ID */
+ if (!silc_idcache_find_by_id_one(id_list->clients, old_id, &id_cache))
return NULL;
client = (SilcClientEntry)id_cache->context;
/* Remove the old entry and add a new one */
- if (!silc_idcache_del_by_context(id_list->clients, client))
+ if (!silc_idcache_del_by_context(id_list->clients, client, server))
return NULL;
/* Check if anyone is watching old nickname */
silc_server_check_watcher_list(server, client, nickname,
SILC_NOTIFY_TYPE_NICK_CHANGE);
- silc_free(client->id);
silc_free(client->nickname);
- client->id = new_id;
+ *client->id = *new_id;
client->nickname = nickname ? strdup(nickname) : NULL;
/* Check if anyone is watching new nickname */
SILC_NOTIFY_TYPE_NICK_CHANGE);
if (!silc_idcache_add(id_list->clients, nicknamec, client->id,
- client, 0, NULL))
+ client))
return NULL;
SILC_LOG_DEBUG(("Replaced"));
SilcChannelEntry
silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
SilcChannelID *id, SilcServerEntry router,
- SilcCipher channel_key, SilcHmac hmac,
- int expire)
+ SilcCipher send_key, SilcCipher receive_key,
+ SilcHmac hmac)
{
SilcChannelEntry channel;
char *channel_namec = NULL;
channel->mode = mode;
channel->id = id;
channel->router = router;
- channel->channel_key = channel_key;
+ channel->send_key = send_key;
+ channel->receive_key = receive_key;
channel->hmac = hmac;
channel->created = channel->updated = time(0);
if (!channel->hmac)
NULL, NULL, NULL, TRUE);
if (!silc_idcache_add(id_list->channels, channel_namec,
- (void *)channel->id, (void *)channel, expire, NULL)) {
+ (void *)channel->id, (void *)channel /*XXX, expire */)) {
silc_hmac_free(channel->hmac);
silc_hash_table_free(channel->user_list);
silc_free(channel);
{
if (entry) {
/* Remove from cache */
- if (!silc_idcache_del_by_context(id_list->channels, entry)) {
+ if (!silc_idcache_del_by_context(id_list->channels, entry, NULL)) {
SILC_LOG_DEBUG(("Unknown channel, did not delete"));
return FALSE;
}
if (entry->ban_list)
silc_hash_table_free(entry->ban_list);
- if (entry->channel_key)
- silc_cipher_free(entry->channel_key);
+ if (entry->send_key)
+ silc_cipher_free(entry->send_key);
+ if (entry->receive_key)
+ silc_cipher_free(entry->receive_key);
if (entry->key) {
memset(entry->key, 0, entry->key_len / 8);
silc_free(entry->key);
/* Remove the old entry and add a new one */
- silc_idcache_del_by_id(id_list->channels, (void *)channel->id);
-
- silc_free(channel->id);
- channel->id = new_id;
-
- silc_idcache_add(id_list->channels, name, channel->id, channel, 0, NULL);
+ silc_idcache_del_by_id(id_list->channels, (void *)channel->id, NULL);
+ *channel->id = *new_id;
+ silc_idcache_add(id_list->channels, name, channel->id, channel);
SILC_LOG_DEBUG(("Replaced"));
silc_idlist_get_channels(SilcIDList id_list, SilcChannelID *channel_id,
SilcUInt32 *channels_count)
{
- SilcIDCacheList list = NULL;
+ SilcList list;
SilcIDCacheEntry id_cache = NULL;
SilcChannelEntry *channels = NULL;
int i = 0;
if (!silc_idcache_get_all(id_list->channels, &list))
return NULL;
- channels = silc_calloc(silc_idcache_list_count(list), sizeof(*channels));
+ channels = silc_calloc(silc_list_count(list), sizeof(*channels));
i = 0;
- silc_idcache_list_first(list, &id_cache);
- channels[i++] = (SilcChannelEntry)id_cache->context;
-
- while (silc_idcache_list_next(list, &id_cache))
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list)))
channels[i++] = (SilcChannelEntry)id_cache->context;
-
- silc_idcache_list_free(list);
} else {
if (!silc_idcache_find_by_id_one(id_list->channels, channel_id, &id_cache))
return NULL;
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2005, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#ifndef IDLIST_H
#define IDLIST_H
-/* Forward declarations */
-typedef struct SilcServerEntryStruct *SilcServerEntry;
-typedef struct SilcClientEntryStruct *SilcClientEntry;
-typedef struct SilcChannelEntryStruct *SilcChannelEntry;
+#include "serverconfig.h"
/* Context for holding cache information to periodically purge
the cache. */
SilcTask task;
} *SilcServerChannelRekey;
-/* Generic rekey context for connections */
-typedef struct {
- /* Current sending encryption key, provided for re-key. The `pfs'
- is TRUE if the Perfect Forward Secrecy is performed in re-key. */
- unsigned char *send_enc_key;
- SilcUInt32 enc_key_len;
- int ske_group;
- bool pfs;
- SilcUInt32 timeout;
- void *context;
-} *SilcServerRekey;
-
/* ID List Entry status flags. */
typedef SilcUInt8 SilcIDListStatus;
#define SILC_IDLIST_STATUS_NONE 0x00 /* No status */
Note that some of the fields may be NULL.
*/
-typedef struct {
- /* Send and receive symmetric keys */
- SilcCipher send_key;
- SilcCipher receive_key;
-
- /* HMAC */
- SilcHmac hmac_send;
- SilcHmac hmac_receive;
-
- /* Packet sequence numbers */
- SilcUInt32 psn_send;
- SilcUInt32 psn_receive;
-
- /* Hash selected in the SKE protocol, NULL if not needed at all */
+struct SilcIDListDataObject {
+ SilcConnectionType conn_type; /* Connection type */
+ SilcServerConnection sconn; /* Connection context */
+ SilcSKERekeyMaterial rekey; /* Rekey material */
SilcHash hash;
/* Public key */
SilcPublicKey public_key;
unsigned char fingerprint[20];
- /* Re-key context */
- SilcServerRekey rekey;
-
long last_receive; /* Time last received data */
long last_sent; /* Time last sent data */
unsigned long created; /* Time when entry was created */
SilcIDListStatus status; /* Status mask of the entry */
-} *SilcIDListData, SilcIDListDataStruct;
+};
/*
SILC Server entry object.
ID of the channel. This includes all the information SILC will ever
need.
- bool global_users
+ SilcBool global_users
Boolean value to tell whether there are users outside this server
on this channel. This is set to TRUE if router sends message to
whose cell this channel belongs to. This is used to route messages
to this channel.
- SilcCipher channel_key
+ SilcCipher send_key
+ SilcCipher receive_key
The key of the channel (the cipher actually).
SilcServerEntry router;
/* Channel keys */
- SilcCipher channel_key;
+ SilcCipher send_key;
+ SilcCipher receive_key;
unsigned char *key;
SilcUInt32 key_len;
SilcHmac hmac;
channel entry).
*/
-typedef struct SilcIDListStruct {
+struct SilcIDListStruct {
SilcIDCache servers;
SilcIDCache clients;
SilcIDCache channels;
-} *SilcIDList;
+};
/*
ID Entry for Unknown connections.
typedef struct {
/* Generic data structure. DO NOT add anything before this! */
SilcIDListDataStruct data;
+ SilcServerConfigRef cconfig;
+ SilcServerConfigRef sconfig;
+ SilcServerConfigRef rconfig;
+ SilcServer server;
+ const char *hostname;
+ const char *ip;
+ SilcUInt16 port;
} *SilcUnknownEntry;
/* Prototypes */
void silc_idlist_add_data(void *entry, SilcIDListData idata);
void silc_idlist_del_data(void *entry);
-SILC_TASK_CALLBACK_GLOBAL(silc_idlist_purge);
+SILC_TASK_CALLBACK(silc_idlist_purge);
SilcServerEntry
silc_idlist_add_server(SilcIDList id_list,
char *server_name, int server_type,
void *connection);
SilcServerEntry
silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id,
- bool registered, SilcIDCacheEntry *ret_entry);
+ SilcBool registered, SilcIDCacheEntry *ret_entry);
SilcServerEntry
silc_idlist_find_server_by_name(SilcIDList id_list, char *name,
- bool registered, SilcIDCacheEntry *ret_entry);
+ SilcBool registered, SilcIDCacheEntry *ret_entry);
SilcServerEntry
silc_idlist_find_server_by_conn(SilcIDList id_list, char *hostname,
- int port, bool registered,
+ int port, SilcBool registered,
SilcIDCacheEntry *ret_entry);
SilcServerEntry
silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
SilcClientEntry
silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
char *userinfo, SilcClientID *id,
- SilcServerEntry router, void *connection,
- int expire);
+ SilcServerEntry router, void *connection);
int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry);
int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
char *server,
SilcUInt32 *clients_count);
SilcClientEntry
silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
- bool registered, SilcIDCacheEntry *ret_entry);
+ SilcBool registered, SilcIDCacheEntry *ret_entry);
SilcClientEntry
silc_idlist_replace_client_id(SilcServer server,
SilcIDList id_list, SilcClientID *old_id,
SilcClientID *new_id, const char *nickname);
void silc_idlist_client_destructor(SilcIDCache cache,
SilcIDCacheEntry entry,
- void *context);
+ void *dest_context,
+ void *app_context);
SilcChannelEntry
silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
SilcChannelID *id, SilcServerEntry router,
- SilcCipher channel_key, SilcHmac hmac,
- int expire);
+ SilcCipher send_key, SilcCipher receive_key,
+ SilcHmac hmac);
int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry);
SilcChannelEntry
silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
GNU General Public License for more details.
*/
-/*
- * Server packet routines to handle received packets.
- */
-/* $Id$ */
#include "serverincludes.h"
#include "server_internal.h"
/* Received notify packet. Server can receive notify packets from router.
Server then relays the notify messages to clients if needed. */
-void silc_server_notify(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+static void silc_server_notify_process(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacket packet,
+ SilcBuffer buffer)
{
+ SilcIDListData idata = silc_packet_get_context(sock);
SilcNotifyPayload payload;
SilcNotifyType type;
SilcArgumentPayload args;
- SilcChannelID *channel_id = NULL, *channel_id2;
- SilcClientID *client_id, *client_id2;
- SilcServerID *server_id;
- SilcIdType id_type;
+ SilcChannelID channel_id;
+ SilcID id, id2;
SilcChannelEntry channel = NULL;
SilcClientEntry client = NULL, client2 = NULL;
SilcServerEntry server_entry = NULL;
SilcIDCacheEntry cache = NULL;
SilcHashTableList htl;
SilcUInt32 mode;
- unsigned char *tmp;
- SilcUInt32 tmp_len;
- bool local;
+ unsigned char *tmp, *tmp2;
+ SilcUInt32 tmp_len, tmp2_len;
+ SilcBool local, ret;
- if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+ if (idata->conn_type == SILC_CONN_CLIENT ||
packet->src_id_type != SILC_ID_SERVER || !packet->dst_id) {
SILC_LOG_DEBUG(("Bad notify packet received"));
return;
before processing it. */
if (packet->dst_id_type == SILC_ID_CLIENT) {
SilcIDListData idata;
- SilcSocketConnection dst_sock;
+ SilcPacketStream dst_sock;
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
&idata, NULL);
if (dst_sock)
/* Relay the packet */
- silc_server_relay_packet(server, dst_sock, idata->send_key,
- idata->hmac_send, idata->psn_send++,
- packet, TRUE);
+ silc_server_packet_route(server, dst_sock, packet);
}
/* Parse the Notify Payload */
- payload = silc_notify_payload_parse(packet->buffer->data,
- packet->buffer->len);
+ payload = silc_notify_payload_parse(buffer->data, silc_buffer_len(buffer));
if (!payload)
return;
the router is buggy. If this packet is coming from router then it must
have the broadcast flag set already and we won't do anything. */
if (server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_SERVER &&
+ idata->conn_type == SILC_CONN_SERVER &&
!(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
SILC_LOG_DEBUG(("Broadcasting received Notify packet"));
if (packet->dst_id_type == SILC_ID_CHANNEL) {
/* Packet is destined to channel */
- channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- packet->dst_id_type);
- if (!channel_id)
+ if (!silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type, &channel_id,
+ sizeof(channel_id)))
goto out;
silc_server_packet_send_dest(server, SILC_PRIMARY_ROUTE(server),
packet->type, packet->flags |
SILC_PACKET_FLAG_BROADCAST,
- channel_id, SILC_ID_CHANNEL,
- packet->buffer->data,
- packet->buffer->len, FALSE);
- silc_server_backup_send_dest(server, sock->user_data,
+ &channel_id, SILC_ID_CHANNEL,
+ buffer->data, silc_buffer_len(buffer));
+ silc_server_backup_send_dest(server, (SilcServerEntry)idata,
packet->type, packet->flags,
- channel_id, SILC_ID_CHANNEL,
- packet->buffer->data, packet->buffer->len,
+ &channel_id, SILC_ID_CHANNEL,
+ buffer->data, silc_buffer_len(buffer),
FALSE, TRUE);
} else {
/* Packet is destined to client or server */
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
packet->type,
packet->flags | SILC_PACKET_FLAG_BROADCAST,
- packet->buffer->data, packet->buffer->len,
- FALSE);
- silc_server_backup_send(server, sock->user_data,
+ buffer->data, silc_buffer_len(buffer));
+ silc_server_backup_send(server, (SilcServerEntry)idata,
packet->type, packet->flags,
- packet->buffer->data, packet->buffer->len,
+ buffer->data, silc_buffer_len(buffer),
FALSE, TRUE);
}
}
*/
SILC_LOG_DEBUG(("JOIN notify"));
- if (channel_id)
- silc_free(channel_id);
-
/* Get Channel ID */
- tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
- if (!tmp)
- goto out;
- channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!channel_id)
+ if (!silc_argument_get_decoded(args, 2, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
SILC_LOG_DEBUG(("Notify for unknown channel"));
- silc_free(channel_id);
goto out;
}
}
- silc_free(channel_id);
/* Get client ID */
- tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
- if (!tmp)
- goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!client_id)
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* If the the client is not in local list we check global list (ie. the
channel will be global channel) and if it does not exist then create
entry for the client. */
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, server->server_type,
+ SILC_ID_GET_ID(id),
+ server->server_type,
&cache);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, server->server_type,
+ SILC_ID_GET_ID(id),
+ server->server_type,
&cache);
if (!client) {
/* If router did not find the client the it is bogus */
- if (server->server_type != SILC_SERVER) {
- silc_free(client_id);
+ if (server->server_type != SILC_SERVER)
goto out;
- }
client =
silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
- silc_id_dup(client_id, SILC_ID_CLIENT),
- sock->user_data, NULL, 0);
+ silc_id_dup(SILC_ID_GET_ID(id),
+ SILC_ID_CLIENT),
+ (SilcServerEntry)idata, NULL);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
- silc_free(client_id);
goto out;
}
client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
}
}
- silc_free(client_id);
/* Do not process the notify if the client is not registered */
if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED))
/* Send to channel */
silc_server_packet_send_to_channel(server, sock, channel, packet->type,
- FALSE, TRUE, packet->buffer->data,
- packet->buffer->len, FALSE);
+ FALSE, TRUE, buffer->data,
+ silc_buffer_len(buffer));
if (server->server_type != SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_ROUTER)
+ idata->conn_type == SILC_CONN_ROUTER)
/* The channel is global now */
channel->global_users = TRUE;
/* JOIN the global client to the channel (local clients (if router
created the channel) is joined in the pending JOIN command). */
chl = silc_calloc(1, sizeof(*chl));
+ if (!chl)
+ goto out;
chl->client = client;
chl->channel = channel;
if (server->server_type != SILC_ROUTER ||
- sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ idata->conn_type == SILC_CONN_ROUTER) {
/* If founder auth is set, first client is not automatically founder. */
if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
/* If this is the first one on the channel then it is the founder of
channel->user_count++;
channel->disabled = FALSE;
- /* Make sure we don't expire clients that are on channel */
- if (cache)
- cache->expire = 0;
-
/* Update statistics */
if (server->server_type == SILC_ROUTER) {
- if (sock->type != SILC_SOCKET_TYPE_ROUTER)
+ if (idata->conn_type != SILC_CONN_ROUTER)
server->stat.cell_chanclients++;
server->stat.chanclients++;
}
*/
SILC_LOG_DEBUG(("LEAVE notify"));
- if (!channel_id) {
- channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- packet->dst_id_type);
- if (!channel_id)
- goto out;
- }
+ if (!silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type, &channel_id,
+ sizeof(channel_id)))
+ goto out;
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ &channel_id, NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ &channel_id, NULL);
if (!channel) {
SILC_LOG_DEBUG(("Notify for unknown channel"));
- silc_free(channel_id);
goto out;
}
}
/* Get client ID */
- tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
- if (!tmp) {
- silc_free(channel_id);
- goto out;
- }
- client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!client_id) {
- silc_free(channel_id);
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
goto out;
- }
/* Get client entry */
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
+ SILC_ID_GET_ID(id), TRUE, NULL);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, NULL);
- if (!client) {
- silc_free(client_id);
- silc_free(channel_id);
+ SILC_ID_GET_ID(id), TRUE, NULL);
+ if (!client)
goto out;
- }
}
- silc_free(client_id);
- silc_free(channel_id);
/* Check if on channel */
if (!silc_server_client_on_channel(client, channel, NULL))
/* Send the leave notify to channel */
silc_server_packet_send_to_channel(server, sock, channel, packet->type,
- FALSE, TRUE, packet->buffer->data,
- packet->buffer->len, FALSE);
+ FALSE, TRUE, buffer->data,
+ silc_buffer_len(buffer));
/* Remove the user from channel */
silc_server_remove_from_one_channel(server, sock, channel, client, FALSE);
SILC_LOG_DEBUG(("SIGNOFF notify"));
/* Get client ID */
- tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
- if (!tmp)
- goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!client_id)
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* Get client entry */
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, &cache);
+ SILC_ID_GET_ID(id), TRUE, &cache);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, &cache);
- if (!client) {
- silc_free(client_id);
+ SILC_ID_GET_ID(id), TRUE, &cache);
+ if (!client)
goto out;
- }
}
- silc_free(client_id);
/* Get signoff message */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
if (tmp_len > 128)
- tmp = NULL;
+ tmp_len = 128;
/* Update statistics */
server->stat.clients--;
client->mode = 0;
client->router = NULL;
client->connection = NULL;
- cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
break;
case SILC_NOTIFY_TYPE_TOPIC_SET:
SILC_LOG_DEBUG(("TOPIC SET notify"));
/* Get client ID */
- tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
- if (!tmp)
- goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
- if (!client_id)
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* Get client entry */
- if (id_type == SILC_ID_CLIENT) {
+ if (id.type == SILC_ID_CLIENT) {
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, &cache);
+ SILC_ID_GET_ID(id), TRUE, &cache);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, &cache);
- if (!client) {
- silc_free(client_id);
+ SILC_ID_GET_ID(id),
+ TRUE, &cache);
+ if (!client)
goto out;
- }
}
- silc_free(client_id);
}
/* Get the topic */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
- if (!tmp) {
- silc_free(channel_id);
+ if (!tmp)
goto out;
- }
- if (!channel_id) {
- channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- packet->dst_id_type);
- if (!channel_id)
- goto out;
- }
+ if (!silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type, &channel_id,
+ sizeof(channel_id)))
+ goto out;
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ &channel_id, NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ &channel_id, NULL);
if (!channel) {
SILC_LOG_DEBUG(("Notify for unknown channel"));
- silc_free(channel_id);
goto out;
}
}
- silc_free(channel_id);
if (channel->topic && !strcmp(channel->topic, tmp)) {
SILC_LOG_DEBUG(("Topic is already set and same"));
/* Send the same notify to the channel */
silc_server_packet_send_to_channel(server, NULL, channel, packet->type,
- FALSE, TRUE, packet->buffer->data,
- packet->buffer->len, FALSE);
+ FALSE, TRUE, buffer->data,
+ silc_buffer_len(buffer));
break;
case SILC_NOTIFY_TYPE_NICK_CHANGE:
/*
* Distribute the notify to local clients on the channel
*/
- unsigned char *id, *id2;
char *nickname;
SilcUInt32 nickname_len;
SILC_LOG_DEBUG(("NICK CHANGE notify"));
/* Get old client ID */
- id = silc_argument_get_arg_type(args, 1, &tmp_len);
- if (!id)
- goto out;
- client_id = silc_id_payload_parse_id(id, tmp_len, NULL);
- if (!client_id)
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* Get new client ID */
- id2 = silc_argument_get_arg_type(args, 2, &tmp_len);
- if (!id2)
- goto out;
- client_id2 = silc_id_payload_parse_id(id2, tmp_len, NULL);
- if (!client_id2) {
- silc_free(client_id);
+ if (!silc_argument_get_decoded(args, 2, SILC_ARGUMENT_ID, &id2, NULL))
goto out;
- }
SILC_LOG_DEBUG(("Old Client ID id(%s)",
- silc_id_render(client_id, SILC_ID_CLIENT)));
+ silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CLIENT)));
SILC_LOG_DEBUG(("New Client ID id(%s)",
- silc_id_render(client_id2, SILC_ID_CLIENT)));
+ silc_id_render(SILC_ID_GET_ID(id2), SILC_ID_CLIENT)));
/* From protocol version 1.1 we also get the new nickname */
nickname = silc_argument_get_arg_type(args, 3, &nickname_len);;
/* Replace the Client ID */
client = silc_idlist_replace_client_id(server,
- server->global_list, client_id,
- client_id2, nickname);
+ server->global_list,
+ SILC_ID_GET_ID(id),
+ SILC_ID_GET_ID(id2), nickname);
if (!client)
client = silc_idlist_replace_client_id(server,
- server->local_list, client_id,
- client_id2, nickname);
+ server->local_list,
+ SILC_ID_GET_ID(id),
+ SILC_ID_GET_ID(id2), nickname);
if (client) {
/* Send the NICK_CHANGE notify type to local clients on the channels
this client is joined to. */
+ tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+ tmp2 = silc_argument_get_arg_type(args, 2, &tmp2_len);
silc_server_send_notify_on_channels(server, client, client,
SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
- id, tmp_len, id2, tmp_len,
+ tmp, tmp_len, tmp2, tmp2_len,
nickname, nickname ?
nickname_len : 0);
}
- silc_free(client_id);
- if (!client)
- silc_free(client_id2);
break;
}
SILC_LOG_DEBUG(("CMODE CHANGE notify"));
/* Get client ID */
- tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
- if (!tmp)
- goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
- if (!client_id)
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* Get client entry */
- if (id_type == SILC_ID_CLIENT) {
+ if (id.type == SILC_ID_CLIENT) {
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, &cache);
+ SILC_ID_GET_ID(id), TRUE, &cache);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, &cache);
- if (!client) {
- silc_free(client_id);
+ SILC_ID_GET_ID(id),
+ TRUE, &cache);
+ if (!client)
goto out;
- }
}
}
- silc_free(client_id);
- if (!channel_id) {
- channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- packet->dst_id_type);
- if (!channel_id)
- goto out;
- }
+ if (!silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type, &channel_id,
+ sizeof(channel_id)))
+ goto out;
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ &channel_id, NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ &channel_id, NULL);
if (!channel) {
SILC_LOG_DEBUG(("Notify for unknown channel"));
- silc_free(channel_id);
goto out;
}
}
- silc_free(channel_id);
/* Get the mode */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
if (channel->founder_key)
silc_pkcs_public_key_free(channel->founder_key);
channel->founder_key = NULL;
- silc_pkcs_public_key_payload_decode(tmp, tmp_len,
- &channel->founder_key);
+ silc_public_key_payload_decode(tmp, tmp_len,
+ &channel->founder_key);
}
/* Check also for channel public key list */
SILC_PUT32_MSB(channel->user_limit, ulimit);
silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
- sidp->data, sidp->len,
+ sidp->data, silc_buffer_len(sidp),
mask, 4,
channel->cipher,
channel->cipher ?
channel->passphrase ?
strlen(channel->passphrase) : 0,
NULL, 0,
- chpklist->data, chpklist->len,
+ chpklist->data,
+ silc_buffer_len(chpklist),
(channel->mode &
SILC_CHANNEL_MODE_ULIMIT ?
ulimit : NULL),
silc_hash_table_list(channel->user_list, &htl);
while (silc_hash_table_get(&htl, NULL, (void *)&chl))
if (chl->mode & SILC_CHANNEL_UMODE_CHANFO &&
- chl->client->router != sock->user_data) {
+ chl->client->router != (SilcServerEntry)idata) {
SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
silc_server_send_notify_cmode(server, sock, FALSE, channel,
channel->mode, server->id,
silc_pkcs_public_key_free(channel->founder_key);
channel->founder_key = NULL;
SILC_LOG_DEBUG(("Founder public key received"));
- if (!silc_pkcs_public_key_payload_decode(tmp, tmp_len,
- &channel->founder_key)) {
+ if (!silc_public_key_payload_decode(tmp, tmp_len,
+ &channel->founder_key)) {
SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
mode &= ~SILC_CHANNEL_MODE_FOUNDER_AUTH;
silc_server_send_notify_cmode(server, sock, FALSE, channel,
/* Send the same notify to the channel */
silc_server_packet_send_to_channel(server, NULL, channel, packet->type,
- FALSE, TRUE, packet->buffer->data,
- packet->buffer->len, FALSE);
+ FALSE, TRUE, buffer->data,
+ silc_buffer_len(buffer));
/* Change mode */
channel->mode = mode;
* Distribute the notify to local clients on the channel
*/
SilcChannelClientEntry chl2 = NULL;
- bool notify_sent = FALSE;
+ SilcBool notify_sent = FALSE;
SILC_LOG_DEBUG(("CUMODE CHANGE notify"));
/* Get client ID */
- tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
- if (!tmp)
- goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
- if (!client_id)
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* Get client entry */
- if (id_type == SILC_ID_CLIENT) {
+ if (id.type == SILC_ID_CLIENT) {
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, &cache);
+ SILC_ID_GET_ID(id),
+ TRUE, &cache);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, &cache);
- if (!client) {
- silc_free(client_id);
+ SILC_ID_GET_ID(id),
+ TRUE, &cache);
+ if (!client)
goto out;
- }
}
}
- silc_free(client_id);
- if (!channel_id) {
- channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- packet->dst_id_type);
- if (!channel_id)
- goto out;
- }
+ if (!silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type, &channel_id,
+ sizeof(channel_id)))
+ goto out;
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ &channel_id, NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ &channel_id, NULL);
if (!channel) {
SILC_LOG_DEBUG(("Notify for unknown channel"));
- silc_free(channel_id);
goto out;
}
}
/* Get the mode */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
- if (!tmp) {
- silc_free(channel_id);
+ if (!tmp)
goto out;
- }
SILC_GET32_MSB(mode, tmp);
/* Get target client */
- tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
- if (!tmp)
- goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!client_id)
+ if (!silc_argument_get_decoded(args, 3, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* Get client entry */
client2 = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
+ SILC_ID_GET_ID(id), TRUE, NULL);
if (!client2) {
client2 = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, NULL);
- if (!client2) {
- silc_free(client_id);
+ SILC_ID_GET_ID(id),
+ TRUE, NULL);
+ if (!client2)
goto out;
- }
}
- silc_free(client_id);
if (client) {
/* Check that sender is on channel */
if (channel->founder_key) {
/* Get public key that must be present in notify */
tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
- if (!tmp || !silc_pkcs_public_key_payload_decode(tmp, tmp_len,
- &founder_key)) {
+ if (!tmp || !silc_public_key_payload_decode(tmp, tmp_len,
+ &founder_key)) {
chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
SILC_LOG_DEBUG(("Founder public key not present"));
silc_server_force_cumode_change(server, sock, channel, chl, mode);
if (!notify_sent)
silc_server_packet_send_to_channel(server, sock, channel,
packet->type,
- FALSE, TRUE, packet->buffer->data,
- packet->buffer->len, FALSE);
+ FALSE, TRUE, buffer->data,
+ silc_buffer_len(buffer));
- silc_free(channel_id);
break;
}
SILC_LOG_DEBUG(("INVITE notify"));
/* Get Channel ID */
- tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
- if (!tmp)
- goto out;
- channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!channel_id)
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
SILC_LOG_DEBUG(("Notify for unknown channel"));
- silc_free(channel_id);
goto out;
}
}
- silc_free(channel_id);
-
-#if 0 /* These aren't actually used anywhere or needed, since this
- notify is for handling the invite list (direct invite
- goes to client and is not handled here at all). */
-
- /* Get client ID */
- tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
- if (!tmp)
- goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!client_id)
- goto out;
-
- /* Get client entry */
- client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, &cache);
- if (!client) {
- client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, &cache);
- if (!client) {
- silc_free(client_id);
- goto out;
- }
- }
- silc_free(client_id);
-
- /* Get user's channel entry and check that inviting is allowed. */
- if (server->server_type == SILC_ROUTER) {
- if (!silc_server_client_on_channel(client, channel, &chl))
- goto out;
- if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
- !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
- !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
- SILC_LOG_DEBUG(("Inviting is not allowed"));
- goto out;
- }
- }
-#endif
/* Get the invite action */
tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
if (server->server_type == SILC_ROUTER)
silc_server_packet_send_to_channel(server, sock, channel,
packet->type, FALSE, FALSE,
- packet->buffer->data,
- packet->buffer->len, FALSE);
+ buffer->data,
+ silc_buffer_len(buffer));
}
break;
SILC_LOG_DEBUG(("CHANNEL CHANGE"));
- if (sock->type != SILC_SOCKET_TYPE_ROUTER)
+ if (idata->conn_type != SILC_CONN_ROUTER)
break;
/* Get the old Channel ID */
- tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
- if (!tmp)
- goto out;
- channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!channel_id)
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* Get the channel entry */
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
SILC_LOG_DEBUG(("Notify for unknown channel"));
- silc_free(channel_id);
goto out;
}
}
/* Send the notify to the channel */
silc_server_packet_send_to_channel(server, sock, channel, packet->type,
- FALSE, TRUE, packet->buffer->data,
- packet->buffer->len, FALSE);
+ FALSE, TRUE, buffer->data,
+ silc_buffer_len(buffer));
/* Get the new Channel ID */
- tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
- if (!tmp)
- goto out;
- channel_id2 = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!channel_id2)
+ if (!silc_argument_get_decoded(args, 2, SILC_ARGUMENT_ID, &id2, NULL))
goto out;
SILC_LOG_DEBUG(("Old Channel ID id(%s)",
- silc_id_render(channel_id, SILC_ID_CHANNEL)));
+ silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL)));
SILC_LOG_DEBUG(("New Channel ID id(%s)",
- silc_id_render(channel_id2, SILC_ID_CHANNEL)));
+ silc_id_render(SILC_ID_GET_ID(id2), SILC_ID_CHANNEL)));
/* Replace the Channel ID */
- if (!silc_idlist_replace_channel_id(server->local_list, channel_id,
- channel_id2))
- if (!silc_idlist_replace_channel_id(server->global_list, channel_id,
- channel_id2)) {
- silc_free(channel_id2);
- channel_id2 = NULL;
- }
-
- if (channel_id2) {
+ ret = TRUE;
+ if (!silc_idlist_replace_channel_id(server->local_list,
+ SILC_ID_GET_ID(id),
+ SILC_ID_GET_ID(id2)))
+ if (!silc_idlist_replace_channel_id(server->global_list,
+ SILC_ID_GET_ID(id),
+ SILC_ID_GET_ID(id2)))
+ ret = FALSE;
+
+ if (ret) {
SilcBuffer modes = NULL, users = NULL, users_modes = NULL;
/* Re-announce this channel which ID was changed. */
silc_buffer_push(users, users->data - users->head);
silc_server_packet_send(server, sock,
SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
- users->data, users->len, FALSE);
+ users->data, silc_buffer_len(users));
silc_buffer_free(users);
}
if (modes) {
silc_server_packet_send_dest(server, sock,
SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
channel->id, SILC_ID_CHANNEL,
- modes->data, modes->len, FALSE);
+ modes->data, silc_buffer_len(modes));
silc_buffer_free(modes);
}
if (users_modes) {
SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
channel->id, SILC_ID_CHANNEL,
users_modes->data,
- users_modes->len, FALSE);
+ silc_buffer_len(users_modes));
silc_buffer_free(users_modes);
}
}
}
- silc_free(channel_id);
-
break;
case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
/* Backup router shouldn't accept SERVER_SIGNOFF's from normal routers
when the backup isn't acting as primary router. */
- if (sock->type == SILC_SOCKET_TYPE_SERVER &&
+ if (idata->conn_type == SILC_CONN_SERVER &&
server->backup_router && server->server_type == SILC_BACKUP_ROUTER)
return;
/* Get Server ID */
- tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
- if (!tmp)
- goto out;
- server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!server_id)
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* If the ID is mine, this notify is not allowed. */
- if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
+ if (SILC_ID_SERVER_COMPARE(SILC_ID_GET_ID(id), server->id)) {
SILC_LOG_DEBUG(("Ignoring my own ID for SERVER_SIGNOFF"));
break;
}
/* Get server entry */
server_entry = silc_idlist_find_server_by_id(server->global_list,
- server_id, TRUE, NULL);
+ SILC_ID_GET_ID(id),
+ TRUE, NULL);
local = FALSE;
if (!server_entry) {
server_entry = silc_idlist_find_server_by_id(server->local_list,
- server_id, TRUE, NULL);
+ SILC_ID_GET_ID(id),
+ TRUE, NULL);
local = TRUE;
if (!server_entry) {
/* If we are normal server then we might not have the server. Check
for (i = 1; i < silc_argument_get_arg_num(args); i++) {
/* Get Client ID */
- tmp = silc_argument_get_arg_type(args, i + 1, &tmp_len);
- if (!tmp)
- continue;
- client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!client_id)
+ if (!silc_argument_get_decoded(args, i + 1, SILC_ARGUMENT_ID,
+ &id2, NULL))
continue;
/* Get client entry */
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, &cache);
+ SILC_ID_GET_ID(id),
+ TRUE, &cache);
local = FALSE;
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, &cache);
+ SILC_ID_GET_ID(id),
+ TRUE, &cache);
local = TRUE;
- if (!client) {
- silc_free(client_id);
+ if (!client)
continue;
- }
}
- silc_free(client_id);
/* Update statistics */
server->stat.clients--;
}
}
- silc_free(server_id);
goto out;
}
}
- silc_free(server_id);
/* For local entrys SERVER_SIGNOFF is processed only on backup router.
It is possible that router sends server signoff for a server. If
if (SILC_IS_LOCAL(server_entry)) {
if (server->server_type == SILC_BACKUP_ROUTER) {
sock = server_entry->connection;
- SILC_LOG_DEBUG(("Closing connection %s after SERVER_SIGNOFF",
- sock->hostname));
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- SILC_SET_DISCONNECTING(sock);
+ SILC_LOG_DEBUG(("Closing connection after SERVER_SIGNOFF"));
+ silc_server_free_sock_user_data(server, sock, NULL);
silc_server_close_connection(server, sock);
}
SILC_LOG_DEBUG(("KICKED notify"));
- if (!channel_id) {
- channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- packet->dst_id_type);
- if (!channel_id)
- goto out;
- }
+ if (!silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type, &channel_id,
+ sizeof(channel_id)))
+ goto out;
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ &channel_id, NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ &channel_id, NULL);
if (!channel) {
SILC_LOG_DEBUG(("Notify for unknown channel"));
- silc_free(channel_id);
goto out;
}
}
- silc_free(channel_id);
/* Get client ID */
- tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
- if (!tmp)
- goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!client_id)
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* If the the client is not in local list we check global list */
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
+ SILC_ID_GET_ID(id), TRUE, NULL);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, NULL);
- if (!client) {
- silc_free(client_id);
+ SILC_ID_GET_ID(id), TRUE, NULL);
+ if (!client)
goto out;
- }
}
- silc_free(client_id);
/* If target is founder they cannot be kicked */
if (!silc_server_client_on_channel(client, channel, &chl))
goto out;
/* Get the kicker's Client ID */
- tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
- if (!tmp)
- goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!client_id)
+ if (!silc_argument_get_decoded(args, 3, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* If the the client is not in local list we check global list */
client2 = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
+ SILC_ID_GET_ID(id), TRUE, NULL);
if (!client2) {
client2 = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, NULL);
- if (!client2) {
- silc_free(client_id);
+ SILC_ID_GET_ID(id), TRUE, NULL);
+ if (!client2)
goto out;
- }
}
- silc_free(client_id);
/* Kicker must be operator on channel */
if (!silc_server_client_on_channel(client2, channel, &chl))
/* Send to channel */
silc_server_packet_send_to_channel(server, sock, channel, packet->type,
- FALSE, TRUE, packet->buffer->data,
- packet->buffer->len, FALSE);
+ FALSE, TRUE, buffer->data,
+ silc_buffer_len(buffer));
/* Remove the client from channel's invite list */
if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
SilcArgumentPayload iargs;
tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
ab = silc_argument_payload_encode_one(NULL, tmp, tmp_len, 3);
- iargs = silc_argument_payload_parse(ab->data, ab->len, 1);
+ iargs = silc_argument_payload_parse(ab->data, silc_buffer_len(ab), 1);
silc_server_inviteban_process(server, channel->invite_list, 1, iargs);
silc_buffer_free(ab);
silc_argument_payload_free(iargs);
/*
* Distribute the notify to local clients on channels
*/
- unsigned char *id, *comment;
- SilcUInt32 id_len, comment_len;
+ unsigned char *comment;
+ SilcUInt32 comment_len;
SILC_LOG_DEBUG(("KILLED notify"));
/* Get client ID */
- id = silc_argument_get_arg_type(args, 1, &id_len);
- if (!id)
- goto out;
- client_id = silc_id_payload_parse_id(id, id_len, NULL);
- if (!client_id)
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* If the the client is not in local list we check global list */
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, &cache);
+ SILC_ID_GET_ID(id), TRUE, &cache);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, &cache);
- if (!client) {
- silc_free(client_id);
+ SILC_ID_GET_ID(id),
+ TRUE, &cache);
+ if (!client)
goto out;
- }
}
- silc_free(client_id);
/* If the client is one of ours, then close the connection to the
client now. This removes the client from all channels as well. */
comment_len = 127;
/* Get the killer's Client ID */
- tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
- if (!tmp)
- goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
- if (!client_id)
+ if (!silc_argument_get_decoded(args, 3, SILC_ARGUMENT_ID, &id, NULL))
goto out;
- if (id_type == SILC_ID_CLIENT) {
+ if (id.type == SILC_ID_CLIENT) {
/* If the the client is not in local list we check global list */
client2 = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
+ SILC_ID_GET_ID(id),
+ TRUE, NULL);
if (!client2) {
client2 = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, NULL);
- if (!client2) {
- silc_free(client_id);
+ SILC_ID_GET_ID(id),
+ TRUE, NULL);
+ if (!client2)
goto out;
- }
}
- silc_free(client_id);
/* Killer must be router operator */
if (server->server_type != SILC_SERVER &&
/* Send the notify to local clients on the channels except to the
client who is killed. */
+ tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+ tmp2 = silc_argument_get_arg_type(args, 3, &tmp2_len);
silc_server_send_notify_on_channels(server, client, client,
SILC_NOTIFY_TYPE_KILLED, 3,
- id, id_len, comment, comment_len,
- tmp, tmp_len);
+ tmp, tmp_len, comment, comment_len,
+ tmp2, tmp2_len);
/* Remove the client from all channels */
silc_server_remove_from_channels(server, NULL, client, FALSE, NULL,
client->mode = 0;
client->router = NULL;
client->connection = NULL;
- cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
break;
}
SILC_LOG_DEBUG(("UMODE_CHANGE notify"));
/* Get client ID */
- tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
- if (!tmp)
- goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!client_id)
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* Get client entry */
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
+ SILC_ID_GET_ID(id), TRUE, NULL);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, NULL);
- if (!client) {
- silc_free(client_id);
+ SILC_ID_GET_ID(id), TRUE, NULL);
+ if (!client)
goto out;
- }
}
- silc_free(client_id);
/* Get the mode */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
SILC_LOG_DEBUG(("BAN notify"));
/* Get Channel ID */
- tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
- if (!tmp)
- goto out;
- channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!channel_id)
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
goto out;
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ SILC_ID_GET_ID(id), NULL);
if (!channel) {
SILC_LOG_DEBUG(("Notify for unknown channel"));
- silc_free(channel_id);
goto out;
}
}
- silc_free(channel_id);
/* Get the ban action */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
if (server->server_type == SILC_ROUTER)
silc_server_packet_send_to_channel(server, sock, channel,
packet->type, FALSE, FALSE,
- packet->buffer->data,
- packet->buffer->len, FALSE);
+ buffer->data,
+ silc_buffer_len(buffer));
}
break;
SILC_LOG_DEBUG(("ERROR notify (%d)", error));
if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
- sock->type == SILC_SOCKET_TYPE_ROUTER) {
- tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
- if (tmp) {
- SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
- "the entry from cache"));
- client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!client_id)
- goto out;
- client = silc_idlist_find_client_by_id(server->global_list,
- client_id, FALSE, NULL);
- if (client) {
- if (client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- client->data.public_key,
- client);
+ idata->conn_type == SILC_CONN_ROUTER) {
+ if (!silc_argument_get_decoded(args, 2, SILC_ARGUMENT_ID, &id, NULL))
+ goto out;
- silc_server_remove_from_channels(server, NULL, client, TRUE,
- NULL, TRUE, FALSE);
- silc_idlist_del_data(client);
- silc_idlist_del_client(server->global_list, client);
- }
- silc_free(client_id);
- }
+ SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
+ "the entry from cache"));
+
+ client = silc_idlist_find_client_by_id(server->global_list,
+ SILC_ID_GET_ID(id),
+ FALSE, NULL);
+ if (!client)
+ goto out;
+
+ if (client->data.public_key)
+ silc_hash_table_del_by_context(server->pk_hash,
+ client->data.public_key,
+ client);
+
+ silc_server_remove_from_channels(server, NULL, client, TRUE,
+ NULL, TRUE, FALSE);
+ silc_idlist_del_data(client);
+ silc_idlist_del_client(server->global_list, client);
}
}
break;
case SILC_NOTIFY_TYPE_NONE:
case SILC_NOTIFY_TYPE_MOTD:
break;
+
default:
break;
}
silc_notify_payload_free(payload);
}
+void silc_server_notify(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacket packet)
+{
+ silc_server_notify_process(server, sock, packet, &packet->buffer);
+}
+
void silc_server_notify_list(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
- SilcPacketContext *new;
- SilcBuffer buffer;
+ SilcIDListData idata = silc_packet_get_context(sock);
SilcUInt16 len;
+ SilcBuffer buffer;
SILC_LOG_DEBUG(("Processing Notify List"));
- if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+ if (idata->conn_type == SILC_CONN_CLIENT ||
packet->src_id_type != SILC_ID_SERVER)
return;
- /* Make copy of the original packet context, except for the actual
- data buffer, which we will here now fetch from the original buffer. */
- new = silc_packet_context_alloc();
- new->type = SILC_PACKET_NOTIFY;
- new->flags = packet->flags;
- new->src_id = packet->src_id;
- new->src_id_len = packet->src_id_len;
- new->src_id_type = packet->src_id_type;
- new->dst_id = packet->dst_id;
- new->dst_id_len = packet->dst_id_len;
- new->dst_id_type = packet->dst_id_type;
-
buffer = silc_buffer_alloc(1024);
- new->buffer = buffer;
+ if (!buffer)
+ return;
- while (packet->buffer->len) {
- SILC_GET16_MSB(len, packet->buffer->data + 2);
- if (len > packet->buffer->len)
+ while (silc_buffer_len(&packet->buffer)) {
+ SILC_GET16_MSB(len, packet->buffer.data + 2);
+ if (len > silc_buffer_len(&packet->buffer))
break;
- if (len > buffer->truelen) {
+ if (len > silc_buffer_truelen(buffer)) {
silc_buffer_free(buffer);
buffer = silc_buffer_alloc(1024 + len);
}
silc_buffer_pull_tail(buffer, len);
- silc_buffer_put(buffer, packet->buffer->data, len);
+ silc_buffer_put(buffer, packet->buffer.data, len);
/* Process the Notify */
- silc_server_notify(server, sock, new);
+ silc_server_notify_process(server, sock, packet, buffer);
silc_buffer_push_tail(buffer, len);
- silc_buffer_pull(packet->buffer, len);
+ silc_buffer_pull(&packet->buffer, len);
}
silc_buffer_free(buffer);
- silc_free(new);
}
/* Received private message. This resolves the destination of the message
the destination is not in our server (or router). */
void silc_server_private_message(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
- SilcSocketConnection dst_sock;
+ SilcPacketStream dst_sock;
SilcIDListData idata;
SilcClientEntry client;
+ SilcClientID client_id;
SILC_LOG_DEBUG(("Start"));
error = SILC_STATUS_ERR_NO_SUCH_CLIENT_ID;
if (packet->src_id_type == SILC_ID_CLIENT) {
- SilcClientID *client_id = silc_id_str2id(packet->src_id,
- packet->src_id_len,
- packet->src_id_type);
+ silc_id_str2id(packet->src_id, packet->src_id_len,
+ packet->src_id_type, &client_id, sizeof(client_id));
silc_server_send_notify_dest(server, sock, FALSE,
- client_id, SILC_ID_CLIENT,
+ &client_id, SILC_ID_CLIENT,
SILC_NOTIFY_TYPE_ERROR, 2,
&error, 1,
- idp->data, idp->len);
- silc_free(client_id);
+ idp->data, silc_buffer_len(idp));
} else {
silc_server_send_notify(server, sock, FALSE,
SILC_NOTIFY_TYPE_ERROR, 2,
&error, 1,
- idp->data, idp->len);
+ idp->data, silc_buffer_len(idp));
}
silc_buffer_free(idp);
}
/* Send the private message */
- silc_server_send_private_message(server, dst_sock, idata->send_key,
- idata->hmac_send, idata->psn_send++,
- packet);
+ silc_server_packet_route(server, dst_sock, packet);
}
/* Received private message key packet.. This packet is never for us. It is to
one client to another. */
void silc_server_private_message_key(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
- SilcSocketConnection dst_sock;
+ SilcPacketStream dst_sock;
SilcIDListData idata;
SILC_LOG_DEBUG(("Start"));
return;
/* Relay the packet */
- silc_server_relay_packet(server, dst_sock, idata->send_key,
- idata->hmac_send, idata->psn_send++, packet, FALSE);
+ silc_server_packet_route(server, dst_sock, packet);
}
/* Processes incoming command reply packet. The command reply packet may
call the command reply routine after processing the packet. */
void silc_server_command_reply(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
- SilcBuffer buffer = packet->buffer;
+ SilcBuffer buffer = &packet->buffer;
SilcClientEntry client = NULL;
- SilcSocketConnection dst_sock;
- SilcIDListData idata;
- SilcClientID *id = NULL;
+ SilcClientID id;
SILC_LOG_DEBUG(("Start"));
if (packet->dst_id_type == SILC_ID_CLIENT) {
/* Destination must be one of ours */
- id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT);
- if (!id)
+ if (!silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT,
+ &id, sizeof(id)))
return;
- client = silc_idlist_find_client_by_id(server->local_list, id, TRUE, NULL);
+ client = silc_idlist_find_client_by_id(server->local_list, &id,
+ TRUE, NULL);
if (!client) {
SILC_LOG_ERROR(("Cannot process command reply to unknown client"));
- silc_free(id);
return;
}
}
/* Execute command reply locally for the command */
silc_server_command_reply_process(server, sock, buffer);
- if (packet->dst_id_type == SILC_ID_CLIENT && client && id) {
- /* Relay the packet to the client */
- const SilcBufferStruct p;
-
- dst_sock = (SilcSocketConnection)client->connection;
- idata = (SilcIDListData)client;
-
- silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len
- + packet->dst_id_len + packet->padlen);
- if (!silc_packet_send_prepare(dst_sock, 0, 0, buffer->len,
- idata->hmac_send, (const SilcBuffer)&p)) {
- SILC_LOG_ERROR(("Cannot send packet"));
- return;
- }
- silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
-
- /* Encrypt packet */
- silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++,
- (SilcBuffer)&p, buffer->len);
-
- /* Send the packet */
- silc_server_packet_send_real(server, dst_sock, TRUE);
-
- silc_free(id);
- }
+ /* Relay the packet to the client */
+ if (packet->dst_id_type == SILC_ID_CLIENT && client)
+ silc_server_packet_route(server, client->connection, packet);
}
/* Process received channel message. The message can be originated from
client or server. */
void silc_server_channel_message(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
SilcChannelEntry channel = NULL;
- SilcChannelID *id = NULL;
+ SilcChannelID id;
+ SilcClientID cid;
+ SilcID sid;
void *sender_id = NULL;
SilcClientEntry sender_entry = NULL;
+ SilcIDListData idata;
SilcChannelClientEntry chl;
- bool local = TRUE;
+ SilcBool local = TRUE;
SILC_LOG_DEBUG(("Processing channel message"));
/* Sanity checks */
if (packet->dst_id_type != SILC_ID_CHANNEL) {
SILC_LOG_DEBUG(("Received bad message for channel, dropped"));
- goto out;
+ return;
}
/* Find channel entry */
- id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
- if (!id)
- goto out;
- channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
+ if (!silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL,
+ &id, sizeof(id)))
+ return;
+ channel = silc_idlist_find_channel_by_id(server->local_list, &id, NULL);
if (!channel) {
- channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
+ channel = silc_idlist_find_channel_by_id(server->global_list, &id, NULL);
if (!channel) {
SilcBuffer idp;
unsigned char error;
packet->dst_id_len,
packet->dst_id_type);
if (!idp)
- goto out;
+ return;
error = SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID;
if (packet->src_id_type == SILC_ID_CLIENT) {
- SilcClientID *client_id = silc_id_str2id(packet->src_id,
- packet->src_id_len,
- packet->src_id_type);
+ silc_id_str2id(packet->src_id, packet->src_id_len,
+ packet->src_id_type, &cid, sizeof(cid));
silc_server_send_notify_dest(server, sock, FALSE,
- client_id, SILC_ID_CLIENT,
+ &cid, SILC_ID_CLIENT,
SILC_NOTIFY_TYPE_ERROR, 2,
- &error, 1, idp->data, idp->len);
- silc_free(client_id);
+ &error, 1, idp->data,
+ silc_buffer_len(idp));
} else {
silc_server_send_notify(server, sock, FALSE,
SILC_NOTIFY_TYPE_ERROR, 2,
- &error, 1, idp->data, idp->len);
+ &error, 1, idp->data, silc_buffer_len(idp));
}
silc_buffer_free(idp);
- goto out;
+ return;
}
}
/* See that this client is on the channel. If the original sender is
not client (as it can be server as well) we don't do the check. */
- sender_id = silc_id_str2id(packet->src_id, packet->src_id_len,
- packet->src_id_type);
- if (!sender_id)
- goto out;
- if (packet->src_id_type == SILC_ID_CLIENT) {
+ if (!silc_id_str2id2(packet->src_id, packet->src_id_len,
+ packet->src_id_type, &sid))
+ return;
+ if (sid.type == SILC_ID_CLIENT) {
sender_entry = silc_idlist_find_client_by_id(server->local_list,
- sender_id, TRUE, NULL);
+ SILC_ID_GET_ID(sid),
+ TRUE, NULL);
if (!sender_entry) {
local = FALSE;
sender_entry = silc_idlist_find_client_by_id(server->global_list,
- sender_id, TRUE, NULL);
+ SILC_ID_GET_ID(sid),
+ TRUE, NULL);
}
if (!sender_entry || !silc_server_client_on_channel(sender_entry,
channel, &chl)) {
SILC_LOG_DEBUG(("Client not on channel"));
- goto out;
+ return;
}
/* If channel is moderated check that client is allowed to send
!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
SILC_LOG_DEBUG(("Channel is silenced from normal users"));
- goto out;
+ return;
}
if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS &&
chl->mode & SILC_CHANNEL_UMODE_CHANOP &&
!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
SILC_LOG_DEBUG(("Channel is silenced from operators"));
- goto out;
+ return;
}
if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
SILC_LOG_DEBUG(("Sender is quieted on the channel"));
- goto out;
+ return;
}
/* If the packet is coming from router, but the client entry is local
entry to us then some router is rerouting this to us and it is not
allowed. When the client is local to us it means that we've routed
this packet to network, and now someone is routing it back to us. */
+ idata = silc_packet_get_context(sock);
if (server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_ROUTER && local) {
+ idata->conn_type == SILC_CONN_ROUTER && local) {
SILC_LOG_DEBUG(("Channel message rerouted to the sender, drop it"));
- goto out;
+ return;
}
}
packet for further routing as well, if needed. */
silc_server_packet_relay_to_channel(server, sock, channel, sender_id,
packet->src_id_type, sender_entry,
- packet->buffer->data,
- packet->buffer->len, FALSE);
-
- out:
- silc_free(sender_id);
- silc_free(id);
+ packet->buffer.data,
+ silc_buffer_len(&packet->buffer));
}
/* Received channel key packet. We distribute the key to all of our locally
connected clients on the channel. */
void silc_server_channel_key(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
- SilcBuffer buffer = packet->buffer;
+ SilcBuffer buffer = &packet->buffer;
+ SilcIDListData idata = silc_packet_get_context(sock);
SilcChannelEntry channel;
if (packet->src_id_type != SILC_ID_SERVER ||
(server->server_type == SILC_ROUTER && !server->backup_router &&
- sock->type == SILC_SOCKET_TYPE_ROUTER))
+ idata->conn_type == SILC_CONN_ROUTER))
return;
/* Save the channel key */
channel = silc_server_save_channel_key(server, buffer, NULL);
if (!channel) {
- SILC_LOG_ERROR(("Bad channel key from %s (%s)",
- sock->hostname, sock->ip));
+ SILC_LOG_ERROR(("Bad channel key from %s", idata->sconn->remote_host));
return;
}
if (server->server_type != SILC_BACKUP_ROUTER) {
/* Distribute to local cell backup routers. */
- silc_server_backup_send(server, sock->user_data,
+ silc_server_backup_send(server, (SilcServerEntry)idata,
SILC_PACKET_CHANNEL_KEY, 0,
- buffer->data, buffer->len, FALSE, TRUE);
+ buffer->data, silc_buffer_len(buffer),
+ FALSE, TRUE);
}
}
client. Client becomes registered after calling this functions. */
SilcClientEntry silc_server_new_client(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
- SilcBuffer buffer = packet->buffer;
+ SilcBuffer buffer = &packet->buffer;
+ SilcIDListData idata = silc_packet_get_context(sock);
SilcClientEntry client;
SilcClientID *client_id;
- SilcIDListData idata;
char *username = NULL, *realname = NULL;
SilcUInt16 username_len;
SilcUInt32 id_len, tmp_len;
int ret;
- char *hostname, *nickname, *nicknamec;
+ char *host, *nickname, *nicknamec;
+ const char *hostname, *ip;
SILC_LOG_DEBUG(("Creating new client"));
- if (sock->type != SILC_SOCKET_TYPE_CLIENT)
+ if (idata->conn_type != SILC_CONN_CLIENT)
return NULL;
/* Take client entry */
- client = (SilcClientEntry)sock->user_data;
- idata = (SilcIDListData)client;
+ client = (SilcClientEntry)idata;
+ silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
/* Remove the old cache entry. */
- if (!silc_idcache_del_by_context(server->local_list->clients, client)) {
+ if (!silc_idcache_del_by_context(server->local_list->clients, client,
+ NULL)) {
SILC_LOG_INFO(("Unauthenticated client attempted to register to network"));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_NOT_AUTHENTICATED, NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
}
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_OPERATION_ALLOWED,
"Too many registrations");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
}
silc_free(username);
silc_free(realname);
SILC_LOG_ERROR(("Client %s (%s) sent incomplete information, closing "
- "connection", sock->hostname, sock->ip));
+ "connection", hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
}
silc_free(username);
silc_free(realname);
SILC_LOG_ERROR(("Client %s (%s) did not send its username, closing "
- "connection", sock->hostname, sock->ip));
+ "connection", hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
}
silc_free(username);
silc_free(realname);
SILC_LOG_ERROR(("Client %s (%s) sent bad username string '%s', closing "
- "connection", sock->hostname, sock->ip, username));
+ "connection", hostname, ip, username));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
}
the client's public key. If the hostname is not present then put
it from the resolved name or from the public key. */
if (strchr(username, '@')) {
- SilcPublicKeyIdentifier pident;
+ SilcSILCPublicKey silc_pubkey;
int tlen = strcspn(username, "@");
char *phostname = NULL;
- hostname = silc_memdup(username + tlen + 1, strlen(username) - tlen - 1);
+ host = silc_memdup(username + tlen + 1, strlen(username) - tlen - 1);
- if (strcmp(sock->hostname, sock->ip) &&
- strcmp(sock->hostname, hostname)) {
+ if (strcmp(hostname, ip) && strcmp(hostname, host)) {
silc_free(username);
- silc_free(hostname);
+ silc_free(host);
silc_free(realname);
SILC_LOG_ERROR(("Client %s (%s) sent incomplete information, closing "
- "connection", sock->hostname, sock->ip));
+ "connection", hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
}
- pident = silc_pkcs_decode_identifier(client->data.public_key->identifier);
- if (pident) {
- phostname = strdup(pident->host);
- silc_pkcs_free_identifier(pident);
- }
-
- if (!strcmp(sock->hostname, sock->ip) &&
- phostname && strcmp(phostname, hostname)) {
+ silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC,
+ client->data.public_key);
+ phostname = strdup(silc_pubkey->identifier.host);
+ if (!strcmp(hostname, ip) && phostname && strcmp(phostname, host)) {
silc_free(username);
- silc_free(hostname);
+ silc_free(host);
silc_free(phostname);
silc_free(realname);
SILC_LOG_ERROR(("Client %s (%s) sent incomplete information, closing "
- "connection", sock->hostname, sock->ip));
+ "connection", hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
}
} else {
/* The hostname is not present, add it. */
char *newusername;
- /* XXX For now we cannot take the host name from the public key since
- they are not trusted or we cannot verify them as trusted. Just take
- what the resolved name or address is. */
-#if 0
- if (strcmp(sock->hostname, sock->ip)) {
-#endif
- newusername = silc_calloc(strlen(username) +
- strlen(sock->hostname) + 2,
- sizeof(*newusername));
- strncat(newusername, username, strlen(username));
- strncat(newusername, "@", 1);
- strncat(newusername, sock->hostname, strlen(sock->hostname));
- silc_free(username);
- username = newusername;
-#if 0
- } else {
- SilcPublicKeyIdentifier pident =
- silc_pkcs_decode_identifier(client->data.public_key->identifier);
-
- if (pident) {
- newusername = silc_calloc(strlen(username) +
- strlen(pident->host) + 2,
- sizeof(*newusername));
- strncat(newusername, username, strlen(username));
- strncat(newusername, "@", 1);
- strncat(newusername, pident->host, strlen(pident->host));
- silc_free(username);
- username = newusername;
- silc_pkcs_free_identifier(pident);
- }
- }
-#endif
+ newusername = silc_calloc(strlen(username) + strlen(hostname) + 2,
+ sizeof(*newusername));
+ strncat(newusername, username, strlen(username));
+ strncat(newusername, "@", 1);
+ strncat(newusername, hostname, strlen(hostname));
+ silc_free(username);
+ username = newusername;
}
/* Create Client ID */
strlen(nicknamec), &client_id)) {
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_BAD_NICKNAME, NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
}
/* Add the client again to the ID cache */
silc_idcache_add(server->local_list->clients, nicknamec,
- client_id, client, 0, NULL);
+ client_id, client);
/* Notify our router about new client on the SILC network */
silc_server_send_new_id(server, SILC_PRIMARY_ROUTE(server),
/* Distribute to backup routers */
if (server->server_type == SILC_ROUTER) {
SilcBuffer idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
- silc_server_backup_send(server, sock->user_data, SILC_PACKET_NEW_ID, 0,
- idp->data, idp->len, FALSE, TRUE);
+ silc_server_backup_send(server, NULL, SILC_PACKET_NEW_ID, 0,
+ idp->data, silc_buffer_len(idp), FALSE, TRUE);
silc_buffer_free(idp);
}
servers is connected to the router. */
SilcServerEntry silc_server_new_server(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
- SilcBuffer buffer = packet->buffer;
+ SilcBuffer buffer = &packet->buffer;
+ SilcIDListData idata = silc_packet_get_context(sock);
SilcServerEntry new_server, server_entry;
- SilcServerID *server_id;
- SilcIDListData idata;
+ SilcServerID server_id;
unsigned char *server_name, *server_namec, *id_string;
SilcUInt16 id_len, name_len;
int ret;
- bool local = TRUE;
+ SilcBool local = TRUE;
+ const char *hostname, *ip;
SILC_LOG_DEBUG(("Creating new server"));
- if (sock->type != SILC_SOCKET_TYPE_SERVER &&
- sock->type != SILC_SOCKET_TYPE_ROUTER)
+ if (idata->conn_type != SILC_CONN_SERVER &&
+ idata->conn_type != SILC_CONN_ROUTER)
return NULL;
/* Take server entry */
- new_server = (SilcServerEntry)sock->user_data;
- idata = (SilcIDListData)new_server;
+ new_server = (SilcServerEntry)idata;
+ silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
/* Statistics */
if (server->server_type == SILC_ROUTER)
server->stat.cell_servers++;
/* Remove the old cache entry */
- if (!silc_idcache_del_by_context(server->local_list->servers, new_server)) {
+ if (!silc_idcache_del_by_context(server->local_list->servers, new_server,
+ NULL)) {
if (!silc_idcache_del_by_context(server->global_list->servers,
- new_server)) {
+ new_server, NULL)) {
SILC_LOG_INFO(("Unauthenticated %s attempted to register to "
- "network", (sock->type == SILC_SOCKET_TYPE_SERVER ?
+ "network", (idata->conn_type == SILC_CONN_SERVER ?
"server" : "router")));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_NOT_AUTHENTICATED, NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
}
local = FALSE;
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_OPERATION_ALLOWED,
"Too many registrations");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
}
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
}
- if (id_len > buffer->len) {
+ if (id_len > silc_buffer_len(buffer)) {
silc_free(id_string);
silc_free(server_name);
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
}
}
/* Get Server ID */
- server_id = silc_id_str2id(id_string, id_len, SILC_ID_SERVER);
- if (!server_id) {
+ if (!silc_id_str2id(id_string, id_len, SILC_ID_SERVER, &server_id,
+ sizeof(server_id))) {
silc_free(id_string);
silc_free(server_name);
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
}
silc_free(id_string);
/* Check for valid server ID */
- if (!silc_id_is_valid_server_id(server, server_id, sock)) {
+ if (!silc_id_is_valid_server_id(server, &server_id, sock)) {
SILC_LOG_INFO(("Invalid server ID sent by %s (%s)",
- sock->ip, sock->hostname));
+ ip, hostname));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_BAD_SERVER_ID, NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
silc_free(server_name);
return NULL;
}
/* Check that we do not have this ID already */
server_entry = silc_idlist_find_server_by_id(server->local_list,
- server_id, TRUE, NULL);
+ &server_id, TRUE, NULL);
if (server_entry) {
if (SILC_IS_LOCAL(server_entry)) {
SILC_LOG_ERROR(("Too many registrations from %s (%s)",
- sock->ip, sock->hostname));
+ ip, hostname));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_OPERATION_ALLOWED,
"Too many registrations");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
} else {
- silc_idcache_del_by_context(server->local_list->servers, server_entry);
+ silc_idcache_del_by_context(server->local_list->servers, server_entry,
+ NULL);
}
} else {
server_entry = silc_idlist_find_server_by_id(server->global_list,
- server_id, TRUE, NULL);
+ &server_id, TRUE, NULL);
if (server_entry) {
if (SILC_IS_LOCAL(server_entry)) {
SILC_LOG_ERROR(("Too many registrations from %s (%s)",
- sock->ip, sock->hostname));
+ ip, hostname));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_OPERATION_ALLOWED,
"Too many registrations");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
} else {
silc_idcache_del_by_context(server->global_list->servers,
- server_entry);
+ server_entry, NULL);
}
}
}
SILC_STRING_UTF8, 256, NULL);
if (!server_namec) {
SILC_LOG_ERROR(("Malformed server name from %s (%s)",
- sock->ip, sock->hostname));
+ ip, hostname));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_OPERATION_ALLOWED,
"Malfromed server name");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return NULL;
}
/* Update server entry */
idata->status |= SILC_IDLIST_STATUS_REGISTERED;
new_server->server_name = server_name;
- new_server->id = server_id;
+ new_server->id = silc_id_dup(&server_id, SILC_ID_SERVER);
SILC_LOG_DEBUG(("New server id(%s)",
- silc_id_render(server_id, SILC_ID_SERVER)));
+ silc_id_render(&server_id, SILC_ID_SERVER)));
/* Add again the entry to the ID cache. */
silc_idcache_add(local ? server->local_list->servers :
- server->global_list->servers, server_namec, server_id,
- new_server, 0, NULL);
+ server->global_list->servers, server_namec,
+ new_server->id, new_server);
/* Distribute the information about new server in the SILC network
to our router. If we are normal server we won't send anything
SILC_PRIMARY_ROUTE(server) != sock)
silc_server_send_new_id(server, SILC_PRIMARY_ROUTE(server),
TRUE, new_server->id, SILC_ID_SERVER,
- silc_id_get_len(server_id, SILC_ID_SERVER));
+ silc_id_get_len(&server_id, SILC_ID_SERVER));
if (server->server_type == SILC_ROUTER) {
/* Distribute to backup routers */
SilcBuffer idp = silc_id_payload_encode(new_server->id, SILC_ID_SERVER);
- silc_server_backup_send(server, sock->user_data, SILC_PACKET_NEW_ID, 0,
- idp->data, idp->len, FALSE, TRUE);
+ silc_server_backup_send(server, NULL, SILC_PACKET_NEW_ID, 0, idp->data,
+ silc_buffer_len(idp), FALSE, TRUE);
silc_buffer_free(idp);
}
backup router. If it has been then we'll disable the server and will
ignore everything it will send until the backup router resuming
protocol has been completed. */
- if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
- silc_server_backup_replaced_get(server, server_id, NULL)) {
+ if (idata->conn_type == SILC_CONN_ROUTER &&
+ silc_server_backup_replaced_get(server, &server_id, NULL)) {
/* Send packet to the router indicating that it cannot use this
connection as it has been replaced by backup router. */
SILC_LOG_DEBUG(("Remote router has been replaced by backup router, "
idata->status |= SILC_IDLIST_STATUS_DISABLED;
} else {
/* If it is router announce our stuff to it. */
- if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
+ if (idata->conn_type == SILC_CONN_ROUTER &&
server->server_type == SILC_ROUTER) {
silc_server_announce_servers(server, FALSE, 0, sock);
silc_server_announce_clients(server, 0, sock);
/* Announce our information to backup router */
if (new_server->server_type == SILC_BACKUP_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_SERVER &&
+ idata->conn_type == SILC_CONN_SERVER &&
server->server_type == SILC_ROUTER) {
silc_server_announce_servers(server, TRUE, 0, sock);
silc_server_announce_clients(server, 0, sock);
to be backup router after this setting. */
if (new_server->server_type == SILC_BACKUP_ROUTER) {
SilcServerConfigRouter *backup;
- backup = silc_server_config_find_backup_conn(server, sock->ip);
+ backup = silc_server_config_find_backup_conn(server, (char *)ip);
if (!backup)
- backup = silc_server_config_find_backup_conn(server, sock->hostname);
+ backup = silc_server_config_find_backup_conn(server, (char *)hostname);
if (backup) {
/* Add as our backup router */
silc_server_backup_add(server, new_server, backup->backup_replace_ip,
/* By default the servers connected to backup router are disabled
until backup router has become the primary */
if (server->server_type == SILC_BACKUP_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_SERVER)
+ idata->conn_type == SILC_CONN_SERVER)
idata->status |= SILC_IDLIST_STATUS_DISABLED;
}
information about newly registered clients and servers. */
static void silc_server_new_id_real(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet,
- int broadcast)
+ SilcPacketStream sock,
+ SilcPacket packet,
+ SilcBuffer buffer,
+ SilcBool broadcast)
{
- SilcBuffer buffer = packet->buffer;
+ SilcIDListData idata = silc_packet_get_context(sock);
SilcIDList id_list;
SilcServerEntry router, server_entry;
- SilcSocketConnection router_sock;
+ SilcPacketStream router_sock;
SilcIDPayload idp;
SilcIdType id_type;
- void *id;
+ SilcServerID sender_id;
+ const char *hostname, *ip;
SILC_LOG_DEBUG(("Processing new ID"));
- if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+ if (idata->conn_type == SILC_CONN_CLIENT ||
server->server_type == SILC_SERVER ||
packet->src_id_type != SILC_ID_SERVER)
return;
- idp = silc_id_payload_parse(buffer->data, buffer->len);
+ idp = silc_id_payload_parse(buffer->data, silc_buffer_len(buffer));
if (!idp)
return;
id_type = silc_id_payload_get_type(idp);
+ silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
+
/* Normal server cannot have other normal server connections */
- server_entry = (SilcServerEntry)sock->user_data;
- if (id_type == SILC_ID_SERVER && sock->type == SILC_SOCKET_TYPE_SERVER &&
+ server_entry = (SilcServerEntry)idata;
+ if (id_type == SILC_ID_SERVER && idata->conn_type == SILC_CONN_SERVER &&
server_entry->server_type == SILC_SERVER)
goto out;
- id = silc_id_payload_get_id(idp);
- if (!id)
- goto out;
-
/* If the packet is coming from server then use the sender as the
origin of the the packet. If it came from router then check the real
sender of the packet and use that as the origin. */
- if (sock->type == SILC_SOCKET_TYPE_SERVER) {
+ if (idata->conn_type == SILC_CONN_SERVER) {
id_list = server->local_list;
router_sock = sock;
- router = sock->user_data;
+ router = server_entry;
/* If the sender is backup router and ID is server (and we are not
backup router) then switch the entry to global list. */
router_sock = server->router ? SILC_PRIMARY_ROUTE(server) : sock;
}
} else {
- void *sender_id = silc_id_str2id(packet->src_id, packet->src_id_len,
- packet->src_id_type);
+ silc_id_str2id(packet->src_id, packet->src_id_len,
+ packet->src_id_type, &sender_id, sizeof(sender_id));
router = silc_idlist_find_server_by_id(server->global_list,
- sender_id, TRUE, NULL);
+ &sender_id, TRUE, NULL);
if (!router)
router = silc_idlist_find_server_by_id(server->local_list,
- sender_id, TRUE, NULL);
- silc_free(sender_id);
+ &sender_id, TRUE, NULL);
router_sock = sock;
id_list = server->global_list;
}
case SILC_ID_CLIENT:
{
SilcClientEntry entry;
+ SilcClientID id;
+
+ if (!silc_id_payload_get_id(idp, &id, sizeof(id)))
+ goto out;
/* Check that we do not have this client already */
entry = silc_idlist_find_client_by_id(server->global_list,
- id, server->server_type,
+ &id, server->server_type,
NULL);
if (!entry)
entry = silc_idlist_find_client_by_id(server->local_list,
- id, server->server_type,
+ &id, server->server_type,
NULL);
if (entry) {
SILC_LOG_DEBUG(("Ignoring client that we already have"));
}
SILC_LOG_DEBUG(("New client id(%s) from [%s] %s",
- silc_id_render(id, SILC_ID_CLIENT),
- sock->type == SILC_SOCKET_TYPE_SERVER ?
- "Server" : "Router", sock->hostname));
+ silc_id_render(&id, SILC_ID_CLIENT),
+ idata->conn_type == SILC_CONN_SERVER ?
+ "Server" : "Router", hostname));
/* As a router we keep information of all global information in our
global list. Cell wide information however is kept in the local
list. */
entry = silc_idlist_add_client(id_list, NULL, NULL, NULL,
- id, router, NULL, 0);
+ &id, router, NULL);
if (!entry) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
/* Inform the sender that the ID is not usable */
- silc_server_send_notify_signoff(server, sock, FALSE, id, NULL);
+ silc_server_send_notify_signoff(server, sock, FALSE, &id, NULL);
goto out;
}
entry->nickname = NULL;
entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
- if (sock->type == SILC_SOCKET_TYPE_SERVER)
+ if (idata->conn_type == SILC_CONN_SERVER)
server->stat.cell_clients++;
server->stat.clients++;
} else
silc_server_send_command(server, router_sock,
SILC_COMMAND_GETKEY, ++server->cmd_ident,
- 1, 1, buffer->data, buffer->len);
+ 1, 1, buffer->data,
+ silc_buffer_len(buffer));
}
}
break;
case SILC_ID_SERVER:
{
SilcServerEntry entry;
+ SilcServerID id;
+
+ if (!silc_id_payload_get_id(idp, &id, sizeof(id)))
+ goto out;
/* If the ID is mine, ignore it. */
- if (SILC_ID_SERVER_COMPARE(id, server->id)) {
+ if (SILC_ID_SERVER_COMPARE(&id, server->id)) {
SILC_LOG_DEBUG(("Ignoring my own ID as new ID"));
break;
}
/* If the ID is the sender's ID, ignore it (we have it already) */
- if (SILC_ID_SERVER_COMPARE(id, router->id)) {
+ if (SILC_ID_SERVER_COMPARE(&id, router->id)) {
SILC_LOG_DEBUG(("Ignoring sender's own ID"));
break;
}
/* Check that we do not have this server already */
entry = silc_idlist_find_server_by_id(server->global_list,
- id, server->server_type,
+ &id, server->server_type,
NULL);
if (!entry)
entry = silc_idlist_find_server_by_id(server->local_list,
- id, server->server_type,
+ &id, server->server_type,
NULL);
if (entry) {
SILC_LOG_DEBUG(("Ignoring server that we already have"));
}
SILC_LOG_DEBUG(("New server id(%s) from [%s] %s",
- silc_id_render(id, SILC_ID_SERVER),
- sock->type == SILC_SOCKET_TYPE_SERVER ?
- "Server" : "Router", sock->hostname));
+ silc_id_render(&id, SILC_ID_SERVER),
+ idata->conn_type == SILC_CONN_SERVER ?
+ "Server" : "Router", hostname));
/* As a router we keep information of all global information in our
global list. Cell wide information however is kept in the local
list. */
- entry = silc_idlist_add_server(id_list, NULL, 0, id, router,
+ entry = silc_idlist_add_server(id_list, NULL, 0, &id, router,
router_sock);
if (!entry) {
SILC_LOG_ERROR(("Could not add new server to the ID Cache"));
}
entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
- if (sock->type == SILC_SOCKET_TYPE_SERVER)
+ if (idata->conn_type == SILC_CONN_SERVER)
server->stat.cell_servers++;
server->stat.servers++;
}
/* If the sender of this packet is server and we are router we need to
broadcast this packet to other routers in the network. */
if (broadcast && server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_SERVER &&
+ idata->conn_type == SILC_CONN_SERVER &&
!(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
SILC_LOG_DEBUG(("Broadcasting received New ID packet"));
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
packet->type,
packet->flags | SILC_PACKET_FLAG_BROADCAST,
- buffer->data, buffer->len, FALSE);
- silc_server_backup_send(server, sock->user_data,
+ buffer->data, silc_buffer_len(buffer));
+ silc_server_backup_send(server, (SilcServerEntry)idata,
packet->type, packet->flags,
- packet->buffer->data, packet->buffer->len,
+ packet->buffer.data,
+ silc_buffer_len(&packet->buffer),
FALSE, TRUE);
}
/* Processes incoming New ID packet. New ID Payload is used to distribute
information about newly registered clients and servers. */
-void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
- SilcPacketContext *packet)
+void silc_server_new_id(SilcServer server, SilcPacketStream sock,
+ SilcPacket packet)
{
- silc_server_new_id_real(server, sock, packet, TRUE);
+ silc_server_new_id_real(server, sock, packet, &packet->buffer, TRUE);
}
/* Receoved New Id List packet, list of New ID payloads inside one
packet. Process the New ID payloads one by one. */
-void silc_server_new_id_list(SilcServer server, SilcSocketConnection sock,
- SilcPacketContext *packet)
+void silc_server_new_id_list(SilcServer server, SilcPacketStream sock,
+ SilcPacket packet)
{
- SilcPacketContext *new_id;
+ SilcIDListData idata = silc_packet_get_context(sock);
SilcBuffer idp;
SilcUInt16 id_len;
SILC_LOG_DEBUG(("Processing New ID List"));
- if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+ if (idata->conn_type == SILC_CONN_CLIENT ||
packet->src_id_type != SILC_ID_SERVER)
return;
broadcast this packet to other routers in the network. Broadcast
this list packet instead of multiple New ID packets. */
if (server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_SERVER &&
+ idata->conn_type == SILC_CONN_SERVER &&
!(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
SILC_LOG_DEBUG(("Broadcasting received New ID List packet"));
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
packet->type,
packet->flags | SILC_PACKET_FLAG_BROADCAST,
- packet->buffer->data,
- packet->buffer->len, FALSE);
- silc_server_backup_send(server, sock->user_data,
+ packet->buffer.data,
+ silc_buffer_len(&packet->buffer));
+ silc_server_backup_send(server, (SilcServerEntry)idata,
packet->type, packet->flags,
- packet->buffer->data, packet->buffer->len,
+ packet->buffer.data,
+ silc_buffer_len(&packet->buffer),
FALSE, TRUE);
}
- /* Make copy of the original packet context, except for the actual
- data buffer, which we will here now fetch from the original buffer. */
- new_id = silc_packet_context_alloc();
- new_id->type = SILC_PACKET_NEW_ID;
- new_id->flags = packet->flags & (~SILC_PACKET_FLAG_LIST);
- new_id->src_id = packet->src_id;
- new_id->src_id_len = packet->src_id_len;
- new_id->src_id_type = packet->src_id_type;
- new_id->dst_id = packet->dst_id;
- new_id->dst_id_len = packet->dst_id_len;
- new_id->dst_id_type = packet->dst_id_type;
-
idp = silc_buffer_alloc(256);
- new_id->buffer = idp;
+ if (!idp)
+ return;
- while (packet->buffer->len) {
- SILC_GET16_MSB(id_len, packet->buffer->data + 2);
- if ((id_len > packet->buffer->len) ||
- (id_len > idp->truelen))
+ while (silc_buffer_len(&packet->buffer)) {
+ SILC_GET16_MSB(id_len, packet->buffer.data + 2);
+ if ((id_len > silc_buffer_len(&packet->buffer)) ||
+ (id_len > silc_buffer_truelen(idp)))
break;
silc_buffer_pull_tail(idp, 4 + id_len);
- silc_buffer_put(idp, packet->buffer->data, 4 + id_len);
+ silc_buffer_put(idp, packet->buffer.data, 4 + id_len);
/* Process the New ID */
- silc_server_new_id_real(server, sock, new_id, FALSE);
+ silc_server_new_id_real(server, sock, packet, idp, FALSE);
silc_buffer_push_tail(idp, 4 + id_len);
- silc_buffer_pull(packet->buffer, 4 + id_len);
+ silc_buffer_pull(&packet->buffer, 4 + id_len);
}
silc_buffer_free(idp);
- silc_free(new_id);
}
/* Received New Channel packet. Information about new channels in the
the new channel. This usually comes from router but also normal server
can send this to notify channels it has when it connects to us. */
-void silc_server_new_channel(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+static void silc_server_new_channel_process(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacket packet,
+ SilcBuffer buffer)
{
+ SilcIDListData idata = silc_packet_get_context(sock);
SilcChannelPayload payload;
- SilcChannelID *channel_id;
+ SilcChannelID channel_id;
char *channel_name, *channel_namec = NULL;
SilcUInt32 name_len;
- unsigned char *id;
+ unsigned char *id, cid[32];
SilcUInt32 id_len, cipher_len;
SilcServerEntry server_entry;
SilcChannelEntry channel;
const char *cipher;
- if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+ if (idata->conn_type == SILC_CONN_CLIENT ||
packet->src_id_type != SILC_ID_SERVER ||
server->server_type == SILC_SERVER)
return;
/* Parse the channel payload */
- payload = silc_channel_payload_parse(packet->buffer->data,
- packet->buffer->len);
+ payload = silc_channel_payload_parse(buffer->data, silc_buffer_len(buffer));
if (!payload)
return;
/* Get the channel ID */
- channel_id = silc_channel_get_id_parse(payload);
- if (!channel_id) {
+ if (!silc_channel_get_id_parse(payload, &channel_id)) {
silc_channel_payload_free(payload);
return;
}
id = silc_channel_get_id(payload, &id_len);
- server_entry = (SilcServerEntry)sock->user_data;
+ server_entry = (SilcServerEntry)idata;
- if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ if (idata->conn_type == SILC_CONN_ROUTER) {
/* Add the channel to global list as it is coming from router. It
cannot be our own channel as it is coming from router. */
channel_namec, NULL);
if (!channel) {
SILC_LOG_DEBUG(("New channel id(%s) from [Router] %s",
- silc_id_render(channel_id, SILC_ID_CHANNEL),
- sock->hostname));
+ silc_id_render(&channel_id, SILC_ID_CHANNEL),
+ idata->sconn->remote_host));
channel =
silc_idlist_add_channel(server->global_list, strdup(channel_name),
- 0, channel_id, sock->user_data, NULL, NULL, 0);
+ 0, silc_id_dup(&channel_id, SILC_ID_CHANNEL),
+ (SilcServerEntry)idata, NULL, NULL, NULL);
if (!channel) {
silc_channel_payload_free(payload);
- silc_free(channel_id);
return;
}
channel->disabled = TRUE; /* Disabled until someone JOINs */
SilcBuffer chk;
SILC_LOG_DEBUG(("Channel id(%s) from [Server] %s",
- silc_id_render(channel_id, SILC_ID_CHANNEL),
- sock->hostname));
+ silc_id_render(&channel_id, SILC_ID_CHANNEL),
+ idata->sconn->remote_host));
/* Check that we don't already have this channel */
channel = silc_idlist_find_channel_by_name(server->local_list,
IP and if it is not then create a new ID and enforce the server
to switch the ID. */
if (server_entry->server_type != SILC_BACKUP_ROUTER &&
- !SILC_ID_COMPARE(channel_id, server->id, server->id->ip.data_len)) {
+ !SILC_ID_COMPARE(&channel_id, server->id, server->id->ip.data_len)) {
SilcChannelID *tmp;
SILC_LOG_DEBUG(("Forcing the server to change Channel ID"));
if (silc_id_create_channel_id(server, server->id, server->rng, &tmp)) {
silc_server_send_notify_channel_change(server, sock, FALSE,
- channel_id, tmp);
+ &channel_id, tmp);
silc_channel_payload_free(payload);
- silc_free(channel_id);
silc_free(tmp);
}
/* Create the channel with the provided Channel ID */
channel = silc_server_create_new_channel_with_id(server, NULL, NULL,
channel_name,
- channel_id, FALSE);
+ &channel_id, FALSE);
if (!channel) {
silc_channel_payload_free(payload);
- silc_free(channel_id);
return;
}
channel->disabled = TRUE; /* Disabled until someone JOINs */
#endif
/* Send the new channel key to the server */
- id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
- cipher = silc_cipher_get_name(channel->channel_key);
+ silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid),
+ &id_len);
+ cipher = silc_cipher_get_name(channel->send_key);
cipher_len = strlen(cipher);
- chk = silc_channel_key_payload_encode(id_len, id,
+ chk = silc_channel_key_payload_encode(id_len, cid,
cipher_len, cipher,
channel->key_len / 8,
channel->key);
silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
- chk->data, chk->len, FALSE);
+ chk->data, silc_buffer_len(chk));
silc_buffer_free(chk);
- silc_free(id);
} else {
/* The channel exist by that name, check whether the ID's match.
If they don't then we'll force the server to use the ID we have.
SILC_LOG_DEBUG(("Channel already exists"));
- if (!SILC_ID_CHANNEL_COMPARE(channel_id, channel->id)) {
+ if (!SILC_ID_CHANNEL_COMPARE(&channel_id, channel->id)) {
/* They don't match, send CHANNEL_CHANGE notify to the server to
force the ID change. */
SILC_LOG_DEBUG(("Forcing the server to change Channel ID"));
silc_server_send_notify_channel_change(server, sock, FALSE,
- channel_id, channel->id);
+ &channel_id, channel->id);
silc_channel_payload_free(payload);
- silc_free(channel_id);
/* Wait that server re-announces this channel */
return;
if (silc_hash_table_count(channel->user_list)) {
if (!silc_server_create_channel_key(server, channel, 0)) {
silc_channel_payload_free(payload);
- silc_free(channel_id);
return;
}
}
/* Send to the server */
- id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
- cipher = silc_cipher_get_name(channel->channel_key);
+ silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid),
+ &id_len);
+ cipher = silc_cipher_get_name(channel->send_key);
cipher_len = strlen(cipher);
- chk = silc_channel_key_payload_encode(id_len, id,
+ chk = silc_channel_key_payload_encode(id_len, cid,
cipher_len, cipher,
channel->key_len / 8,
channel->key);
silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
- chk->data, chk->len, FALSE);
+ chk->data, silc_buffer_len(chk));
silc_buffer_free(chk);
- silc_free(id);
}
- silc_free(channel_id);
-
/* Since the channel is coming from server and we also know about it
then send the JOIN notify to the server so that it see's our
users on the channel "joining" the channel. */
silc_buffer_push(users, users->data - users->head);
silc_server_packet_send(server, sock,
SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
- users->data, users->len, FALSE);
+ users->data, silc_buffer_len(users));
silc_buffer_free(users);
}
if (modes) {
silc_server_packet_send_dest(server, sock,
SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
channel->id, SILC_ID_CHANNEL,
- modes->data, modes->len, FALSE);
+ modes->data, silc_buffer_len(modes));
silc_buffer_free(modes);
}
if (users_modes) {
SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
channel->id, SILC_ID_CHANNEL,
users_modes->data,
- users_modes->len, FALSE);
+ silc_buffer_len(users_modes));
silc_buffer_free(users_modes);
}
if (channel->topic) {
broadcast this packet to other routers in the network. Broadcast
this list packet instead of multiple New Channel packets. */
if (server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_SERVER &&
+ idata->conn_type == SILC_CONN_SERVER &&
!(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
SILC_LOG_DEBUG(("Broadcasting received New Channel packet"));
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
packet->type,
packet->flags | SILC_PACKET_FLAG_BROADCAST,
- packet->buffer->data,
- packet->buffer->len, FALSE);
- silc_server_backup_send(server, sock->user_data,
+ buffer->data, silc_buffer_len(buffer));
+ silc_server_backup_send(server, (SilcServerEntry)idata,
packet->type, packet->flags,
- packet->buffer->data, packet->buffer->len,
+ buffer->data, silc_buffer_len(buffer),
FALSE, TRUE);
}
silc_channel_payload_free(payload);
}
+/* Received New Channel packet. Information about new channels in the
+ network are distributed using this packet. Save the information about
+ the new channel. This usually comes from router but also normal server
+ can send this to notify channels it has when it connects to us. */
+
+void silc_server_new_channel(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacket packet)
+{
+ silc_server_new_channel_process(server, sock, packet, &packet->buffer);
+}
+
/* Received New Channel List packet, list of New Channel List payloads inside
one packet. Process the New Channel payloads one by one. */
void silc_server_new_channel_list(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
- SilcPacketContext *new;
+ SilcIDListData idata = silc_packet_get_context(sock);
SilcBuffer buffer;
SilcUInt16 len1, len2;
SILC_LOG_DEBUG(("Processing New Channel List"));
- if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+ if (idata->conn_type == SILC_CONN_CLIENT ||
packet->src_id_type != SILC_ID_SERVER ||
server->server_type == SILC_SERVER)
return;
- /* Make copy of the original packet context, except for the actual
- data buffer, which we will here now fetch from the original buffer. */
- new = silc_packet_context_alloc();
- new->type = SILC_PACKET_NEW_CHANNEL;
- new->flags = packet->flags & (~SILC_PACKET_FLAG_LIST);
- new->src_id = packet->src_id;
- new->src_id_len = packet->src_id_len;
- new->src_id_type = packet->src_id_type;
- new->dst_id = packet->dst_id;
- new->dst_id_len = packet->dst_id_len;
- new->dst_id_type = packet->dst_id_type;
-
buffer = silc_buffer_alloc(512);
- new->buffer = buffer;
+ if (!buffer)
+ return;
- while (packet->buffer->len) {
- SILC_GET16_MSB(len1, packet->buffer->data);
- if ((len1 > packet->buffer->len) ||
- (len1 > buffer->truelen))
+ while (silc_buffer_len(&packet->buffer)) {
+ SILC_GET16_MSB(len1, packet->buffer.data);
+ if ((len1 > silc_buffer_len(&packet->buffer)) ||
+ (len1 > silc_buffer_truelen(buffer)))
break;
- SILC_GET16_MSB(len2, packet->buffer->data + 2 + len1);
- if ((len2 > packet->buffer->len) ||
- (len2 > buffer->truelen))
+ SILC_GET16_MSB(len2, packet->buffer.data + 2 + len1);
+ if ((len2 > silc_buffer_len(&packet->buffer)) ||
+ (len2 > silc_buffer_truelen(buffer)))
break;
silc_buffer_pull_tail(buffer, 8 + len1 + len2);
- silc_buffer_put(buffer, packet->buffer->data, 8 + len1 + len2);
+ silc_buffer_put(buffer, packet->buffer.data, 8 + len1 + len2);
/* Process the New Channel */
- silc_server_new_channel(server, sock, new);
+ silc_server_new_channel_process(server, sock, packet, buffer);
silc_buffer_push_tail(buffer, 8 + len1 + len2);
- silc_buffer_pull(packet->buffer, 8 + len1 + len2);
+ silc_buffer_pull(&packet->buffer, 8 + len1 + len2);
}
silc_buffer_free(buffer);
- silc_free(new);
}
/* Received key agreement packet. This packet is never for us. It is to
one client to another. */
void silc_server_key_agreement(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
- SilcSocketConnection dst_sock;
+ SilcPacketStream dst_sock;
SilcIDListData idata;
SILC_LOG_DEBUG(("Start"));
return;
/* Relay the packet */
- silc_server_relay_packet(server, dst_sock, idata->send_key,
- idata->hmac_send, idata->psn_send++,
- packet, FALSE);
+ silc_server_packet_route(server, dst_sock, packet);
}
/* Received connection auth request packet that is used during connection
method to use. */
void silc_server_connection_auth_request(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
SilcServerConfigClient *client = NULL;
SilcUInt16 conn_type;
int ret;
SilcAuthMethod auth_meth = SILC_AUTH_NONE;
+ const char *hostname, *ip;
if (packet->src_id_type && packet->src_id_type != SILC_ID_CLIENT) {
SILC_LOG_DEBUG(("Request not from client"));
return;
}
+ silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
+
/* Parse the payload */
- ret = silc_buffer_unformat(packet->buffer,
+ ret = silc_buffer_unformat(&packet->buffer,
SILC_STR_UI_SHORT(&conn_type),
SILC_STR_UI_SHORT(NULL),
SILC_STR_END);
if (ret == -1)
return;
- if (conn_type != SILC_SOCKET_TYPE_CLIENT)
+ if (conn_type != SILC_CONN_CLIENT)
return;
/* Get the authentication method for the client */
auth_meth = SILC_AUTH_NONE;
- client = silc_server_config_find_client(server, sock->ip);
+ client = silc_server_config_find_client(server, (char *)ip);
if (!client)
- client = silc_server_config_find_client(server, sock->hostname);
+ client = silc_server_config_find_client(server, (char *)hostname);
if (client) {
if (client->passphrase) {
if (client->publickeys && !server->config->prefer_passphrase_auth)
silc_server_send_connection_auth_request(server, sock, conn_type, auth_meth);
}
-/* Received REKEY packet. The sender of the packet wants to regenerate
- its session keys. This starts the REKEY protocol. */
-
-void silc_server_rekey(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
-{
- SilcProtocol protocol;
- SilcServerRekeyInternalContext *proto_ctx;
- SilcIDListData idata = (SilcIDListData)sock->user_data;
-
- SILC_LOG_DEBUG(("Received rekey request"));
-
- /* If we have other protocol executing we have no other choice but to
- not execute rekey. XXX This is very bad thing. Let's hope this
- doesn't happen often. */
- if (sock->protocol) {
- SILC_LOG_WARNING(("Cannot execute REKEY protocol because other protocol "
- "is executing at the same time"));
- return;
- }
-
- /* Allocate internal protocol context. This is sent as context
- to the protocol. */
- proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
- proto_ctx->server = (void *)server;
- proto_ctx->sock = silc_socket_dup(sock);
- proto_ctx->responder = TRUE;
- proto_ctx->pfs = idata->rekey->pfs;
-
- /* Perform rekey protocol. Will call the final callback after the
- protocol is over. */
- silc_protocol_alloc(SILC_PROTOCOL_SERVER_REKEY,
- &protocol, proto_ctx, silc_server_rekey_final);
- sock->protocol = protocol;
-
- if (proto_ctx->pfs == FALSE)
- /* Run the protocol */
- silc_protocol_execute(protocol, server->schedule, 0, 0);
-}
-
/* Received file transger packet. This packet is never for us. It is to
the client in the packet's destination ID. Sending of this sort of packet
equals sending private message, ie. it is sent point to point from
one client to another. */
void silc_server_ftp(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
- SilcSocketConnection dst_sock;
+ SilcPacketStream dst_sock;
SilcIDListData idata;
SILC_LOG_DEBUG(("Start"));
return;
/* Relay the packet */
- silc_server_relay_packet(server, dst_sock, idata->send_key,
- idata->hmac_send, idata->psn_send++,
- packet, FALSE);
+ silc_server_packet_route(server, dst_sock, packet);
}
typedef struct {
SilcServer server;
- SilcSocketConnection sock;
- SilcPacketContext *packet;
- void *data;
+ SilcPacketStream sock;
+ SilcPacket packet;
+ SilcClientID client_id;
} *SilcServerResumeResolve;
SILC_SERVER_CMD_FUNC(resume_resolve)
{
SilcServerResumeResolve r = (SilcServerResumeResolve)context;
SilcServer server = r->server;
- SilcSocketConnection sock = r->sock;
+ SilcPacketStream sock = r->sock;
SilcServerCommandReplyContext reply = context2;
SilcClientEntry client;
+ const char *hostname, *ip;
SILC_LOG_DEBUG(("Start"));
+ silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
+
if (!reply || !silc_command_get_status(reply->payload, NULL, NULL)) {
SILC_LOG_ERROR(("Client %s (%s) tried to resume unknown client, "
- "closing connection", sock->hostname, sock->ip));
+ "closing connection", hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
goto out;
}
if (reply && silc_command_get(reply->payload) == SILC_COMMAND_WHOIS) {
/* Get entry to the client, and resolve it if we don't have it. */
client = silc_idlist_find_client_by_id(server->local_list,
- r->data, TRUE, NULL);
+ &r->client_id, TRUE, NULL);
if (!client) {
client = silc_idlist_find_client_by_id(server->global_list,
- r->data, TRUE, NULL);
+ &r->client_id, TRUE, NULL);
if (!client) {
SILC_LOG_ERROR(("Client %s (%s) tried to resume unknown client, "
- "closing connection", sock->hostname, sock->ip));
+ "closing connection", hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
goto out;
}
}
if (!(client->mode & SILC_UMODE_DETACHED)) {
SILC_LOG_ERROR(("Client %s (%s) tried to resume un-detached client, "
- "closing connection", sock->hostname, sock->ip));
+ "closing connection", hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
goto out;
}
silc_server_resume_client(server, sock, r->packet);
out:
- silc_socket_free(r->sock);
- silc_packet_context_free(r->packet);
- silc_free(r->data);
+ silc_packet_stream_unref(r->sock);
silc_free(r);
}
that the client is not detached anymore. */
void silc_server_resume_client(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
- SilcBuffer buffer = packet->buffer, buf;
- SilcIDListData idata;
+ SilcBuffer buffer = &packet->buffer, buf;
+ SilcIDListData idata = silc_packet_get_context(sock);
SilcIDCacheEntry id_cache = NULL;
SilcClientEntry detached_client;
- SilcClientID *client_id = NULL;
+ SilcClientID client_id;
unsigned char *id_string, *auth = NULL, *nicknamec = NULL;
+ unsigned char cid[32];
+ SilcUInt32 cid_len;
SilcUInt16 id_len, auth_len = 0;
- int ret;
- bool resolved, local, nick_change = FALSE, resolve = FALSE;
+ SilcBool resolved, local, nick_change = FALSE, resolve = FALSE;
SilcChannelEntry channel;
SilcHashTableList htl;
SilcChannelClientEntry chl;
SilcServerResumeResolve r;
- const char *cipher;
+ const char *cipher, *hostname, *ip;
- ret = silc_buffer_unformat(buffer,
- SILC_STR_UI16_NSTRING(&id_string, &id_len),
- SILC_STR_END);
- if (ret != -1)
- client_id = silc_id_str2id(id_string, id_len, SILC_ID_CLIENT);
+ silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
- if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
+ if (silc_buffer_unformat(buffer,
+ SILC_STR_UI16_NSTRING(&id_string, &id_len),
+ SILC_STR_END) < 0) {
+ if (idata->conn_type == SILC_CONN_CLIENT) {
+ SILC_LOG_ERROR(("Client %s (%s) sent incomplete resume information, "
+ "closing connection", hostname, ip));
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ "Resuming not possible");
+ silc_server_free_sock_user_data(server, sock, NULL);
+ }
+ goto out;
+ }
+
+ silc_id_str2id(id_string, id_len, SILC_ID_CLIENT, &client_id,
+ sizeof(client_id));
+
+ if (idata->conn_type == SILC_CONN_CLIENT) {
/* Client send this and is attempting to resume to old client session */
SilcClientEntry client;
SilcBuffer keyp;
- if (ret != -1) {
- silc_buffer_pull(buffer, 2 + id_len);
- auth = buffer->data;
- auth_len = buffer->len;
- silc_buffer_push(buffer, 2 + id_len);
- }
+ silc_buffer_pull(buffer, 2 + id_len);
+ auth = buffer->data;
+ auth_len = silc_buffer_len(buffer);
+ silc_buffer_push(buffer, 2 + id_len);
- if (!client_id || auth_len < 128) {
+ if (auth_len < 128) {
SILC_LOG_ERROR(("Client %s (%s) sent incomplete resume information, "
- "closing connection", sock->hostname, sock->ip));
+ "closing connection", hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- silc_free(client_id);
- return;
+ silc_server_free_sock_user_data(server, sock, NULL);
+ goto out;
}
/* Take client entry of this connection */
- client = (SilcClientEntry)sock->user_data;
- idata = (SilcIDListData)client;
+ client = (SilcClientEntry)idata;
/* Get entry to the client, and resolve it if we don't have it. */
- detached_client = silc_server_query_client(server, client_id, FALSE,
+ detached_client = silc_server_query_client(server, &client_id, FALSE,
&resolved);
if (!detached_client) {
if (resolved) {
SILC_LOG_DEBUG(("Resolving client"));
r = silc_calloc(1, sizeof(*r));
if (!r)
- return;
+ goto out;
+ silc_packet_stream_ref(sock);
r->server = server;
- r->sock = silc_socket_dup(sock);
- r->packet = silc_packet_context_dup(packet);
- r->data = client_id;
+ r->sock = sock;
+ r->packet = packet;
+ r->client_id = client_id;
silc_server_command_pending(server, SILC_COMMAND_WHOIS,
server->cmd_ident,
silc_server_command_resume_resolve, r);
+ return;
} else {
SILC_LOG_ERROR(("Client %s (%s) tried to resume unknown client, "
- "closing connection", sock->hostname, sock->ip));
+ "closing connection", hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- silc_free(client_id);
+ silc_server_free_sock_user_data(server, sock, NULL);
+ goto out;
}
- return;
}
if (detached_client->data.status & SILC_IDLIST_STATUS_RESUMED) {
SILC_LOG_ERROR(("Client %s (%s) tried to attach more than once, "
- "closing connection", sock->hostname, sock->ip));
+ "closing connection", hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- silc_free(client_id);
-
- return;
+ silc_server_free_sock_user_data(server, sock, NULL);
+ goto out;
}
if (detached_client->resuming_client &&
detached_client->resuming_client != client) {
SILC_LOG_ERROR(("Client %s (%s) tried to attach more than once, "
- "closing connection", sock->hostname, sock->ip));
+ "closing connection", hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- silc_free(client_id);
-
- return;
+ silc_server_free_sock_user_data(server, sock, NULL);
+ goto out;
}
if (!detached_client->resuming_client)
/* The client info is being resolved. Reprocess this packet after
receiving the reply to the query. */
SILC_LOG_DEBUG(("Resolving client info"));
- silc_server_query_client(server, client_id, TRUE, NULL);
+ silc_server_query_client(server, &client_id, TRUE, NULL);
r = silc_calloc(1, sizeof(*r));
if (!r)
return;
+ silc_packet_stream_ref(sock);
r->server = server;
- r->sock = silc_socket_dup(sock);
- r->packet = silc_packet_context_dup(packet);
- r->data = client_id;
+ r->sock = sock;
+ r->packet = packet;
+ r->client_id = client_id;
silc_server_command_pending(server, SILC_COMMAND_WHOIS,
server->cmd_ident,
silc_server_command_resume_resolve, r);
}
if (server->server_type == SILC_SERVER) {
SILC_LOG_ERROR(("Client %s (%s) tried to resume un-detached client, "
- "closing connection", sock->hostname, sock->ip));
+ "closing connection", hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- silc_free(client_id);
- return;
+ silc_server_free_sock_user_data(server, sock, NULL);
+ goto out;
}
}
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- silc_free(client_id);
+ silc_server_free_sock_user_data(server, sock, NULL);
+ goto out;
} else {
/* We must retrieve the detached client's public key by sending
GETKEY command. Reprocess this packet after receiving the key */
- SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
- SilcSocketConnection dest_sock =
- silc_server_get_client_route(server, NULL, 0, client_id, NULL, NULL);
+ SilcBuffer idp = silc_id_payload_encode(&client_id, SILC_ID_CLIENT);
+ SilcPacketStream dest_sock =
+ silc_server_get_client_route(server, NULL, 0, &client_id,
+ NULL, NULL);
SILC_LOG_DEBUG(("Resolving client public key"));
silc_server_send_command(server, dest_sock ? dest_sock :
SILC_PRIMARY_ROUTE(server),
SILC_COMMAND_GETKEY, ++server->cmd_ident,
- 1, 1, idp->data, idp->len);
+ 1, 1, idp->data, silc_buffer_len(idp));
r = silc_calloc(1, sizeof(*r));
- if (!r) {
- silc_free(client_id);
+ if (!r)
return;
- }
-
+ silc_packet_stream_ref(sock);
r->server = server;
- r->sock = silc_socket_dup(sock);
- r->packet = silc_packet_context_dup(packet);
+ r->sock = sock;
+ r->packet = packet;
+ r->client_id = client_id;
silc_server_command_pending(server, SILC_COMMAND_GETKEY,
server->cmd_ident,
silc_server_command_resume_resolve, r);
silc_buffer_free(idp);
+ return;
}
- silc_free(client_id);
- return;
} else if (!silc_pkcs_public_key_compare(detached_client->data.public_key,
idata->public_key)) {
/* We require that the connection and resuming authentication data
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- silc_free(client_id);
- return;
+ silc_server_free_sock_user_data(server, sock, NULL);
+ goto out;
}
/* Verify the authentication payload. This has to be successful in
idata->hash, detached_client->id,
SILC_ID_CLIENT)) {
SILC_LOG_ERROR(("Client %s (%s) resume authentication failed, "
- "closing connection", sock->hostname, sock->ip));
+ "closing connection", hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- silc_free(client_id);
- return;
+ silc_server_free_sock_user_data(server, sock, NULL);
+ goto out;
}
/* Check nickname */
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_BAD_NICKNAME,
"Malformed nickname, cannot resume");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- return;
+ silc_server_free_sock_user_data(server, sock, NULL);
+ goto out;
}
/* If the ID is not based in our ID then change it */
if (!SILC_ID_COMPARE(detached_client->id, server->id,
server->id->ip.data_len)) {
- silc_free(client_id);
+ SilcClientID *new_id;
if (!silc_id_create_client_id(server, server->id, server->rng,
server->md5hash, nicknamec,
- strlen(nicknamec), &client_id)) {
+ strlen(nicknamec), &new_id)) {
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_BAD_NICKNAME,
"Resuming not possible");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- return;
+ silc_server_free_sock_user_data(server, sock, NULL);
+ goto out;
}
nick_change = TRUE;
+ client_id = *new_id;
+ silc_free(new_id);
}
/* Now resume the client to the network */
silc_schedule_task_del_by_context(server->schedule, detached_client);
- sock->user_data = detached_client;
+ silc_packet_set_context(sock, detached_client);
detached_client->connection = sock;
if (detached_client->data.public_key)
/* Send to primary router */
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
SILC_PACKET_RESUME_CLIENT, 0,
- buf->data, buf->len, TRUE);
+ buf->data, silc_buffer_len(buf));
silc_server_backup_send(server, client->router,
SILC_PACKET_RESUME_CLIENT, 0,
- buf->data, buf->len, TRUE, TRUE);
+ buf->data, silc_buffer_len(buf), TRUE, TRUE);
/* As router we must deliver this packet directly to the original
server whom this client was earlier. */
client->router->server_type != SILC_ROUTER)
silc_server_packet_send(server, client->router->connection,
SILC_PACKET_RESUME_CLIENT, 0,
- buf->data, buf->len, TRUE);
+ buf->data, silc_buffer_len(buf));
silc_buffer_free(buf);
client->router = NULL;
/* Notify about Client ID change, nickname doesn't actually change. */
silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
SILC_BROADCAST(server),
- client->id, client_id,
+ client->id, &client_id,
client->nickname);
}
/* Send the new client ID to the client. After this client may start
receiving other packets, and may start sending packets too. */
- silc_server_send_new_id(server, sock, FALSE, client_id, SILC_ID_CLIENT,
- silc_id_get_len(client_id, SILC_ID_CLIENT));
+ silc_server_send_new_id(server, sock, FALSE, &client_id, SILC_ID_CLIENT,
+ silc_id_get_len(&client_id, SILC_ID_CLIENT));
if (nick_change) {
/* Send NICK change notify to channels as well. */
SilcBuffer oidp, nidp;
oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
- nidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
+ nidp = silc_id_payload_encode(&client_id, SILC_ID_CLIENT);
silc_server_send_notify_on_channels(server, NULL, client,
SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
- oidp->data, oidp->len,
- nidp->data, nidp->len,
+ oidp->data, silc_buffer_len(oidp),
+ nidp->data, silc_buffer_len(nidp),
client->nickname,
strlen(client->nickname));
silc_buffer_free(oidp);
}
/* Add the client again to the ID cache to get it to correct list */
- if (!silc_idcache_del_by_context(server->local_list->clients, client))
- silc_idcache_del_by_context(server->global_list->clients, client);
+ if (!silc_idcache_del_by_context(server->local_list->clients, client,
+ NULL))
+ silc_idcache_del_by_context(server->global_list->clients, client, NULL);
silc_free(client->id);
- client->id = client_id;
- client_id = NULL;
+ *client->id = client_id;
silc_idcache_add(server->local_list->clients, nicknamec,
- client->id, client, 0, NULL);
+ client->id, client);
/* Send some nice info to the client */
silc_server_send_connect_notifys(server, sock, client);
/* Send all channel keys of channels the client has joined */
silc_hash_table_list(client->channels, &htl);
while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
- bool created = FALSE;
+ SilcBool created = FALSE;
channel = chl->channel;
if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
continue;
/* If we don't have channel key, then create one */
- if (!channel->channel_key) {
+ if (!channel->send_key) {
if (!silc_server_create_channel_key(server, channel, 0))
continue;
created = TRUE;
}
- id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- cipher = silc_cipher_get_name(channel->channel_key);
+ silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid),
+ &cid_len);
+ cipher = silc_cipher_get_name(channel->send_key);
keyp =
- silc_channel_key_payload_encode(silc_id_get_len(channel->id,
- SILC_ID_CHANNEL),
- id_string,
+ silc_channel_key_payload_encode(cid_len, cid,
strlen(cipher), cipher,
channel->key_len / 8, channel->key);
- silc_free(id_string);
/* Send the channel key to the client */
silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
- keyp->data, keyp->len, FALSE);
+ keyp->data, silc_buffer_len(keyp));
/* Distribute the channel key to channel */
if (created) {
server->server_type == SILC_ROUTER ?
FALSE : !server->standalone);
silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
- keyp->data, keyp->len, FALSE, TRUE);
+ keyp->data, silc_buffer_len(keyp),
+ FALSE, TRUE);
}
silc_buffer_free(keyp);
}
silc_hash_table_list_reset(&htl);
- } else if (sock->type != SILC_SOCKET_TYPE_CLIENT) {
+ } else if (idata->conn_type != SILC_CONN_CLIENT) {
/* Server or router sent this to us to notify that that a client has
been resumed. */
SilcServerEntry server_entry;
- SilcServerID *server_id;
-
- if (!client_id) {
- SILC_LOG_DEBUG(("Malformed resuming packet"));
- return;
- }
+ SilcServerID server_id;
/* Get entry to the client, and resolve it if we don't have it. */
detached_client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE,
+ &client_id, TRUE,
&id_cache);
if (!detached_client) {
detached_client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE,
+ &client_id, TRUE,
&id_cache);
if (!detached_client) {
SILC_LOG_DEBUG(("Resuming client is unknown"));
- silc_free(client_id);
- return;
+ goto out;
}
}
SILC_LOG_DEBUG(("Attempting to re-resume client, killing both"));
silc_server_kill_client(server, detached_client, NULL,
server->id, SILC_ID_SERVER);
- silc_free(client_id);
- return;
+ goto out;
}
/* Check whether client is detached at all */
if (!(detached_client->mode & SILC_UMODE_DETACHED)) {
SILC_LOG_DEBUG(("Client is not detached"));
- silc_free(client_id);
- return;
+ goto out;
}
/* Check nickname */
nicknamec = silc_identifier_check(detached_client->nickname,
strlen(detached_client->nickname),
SILC_STRING_UTF8, 128, NULL);
- if (!nicknamec) {
- silc_free(client_id);
- return;
- }
+ if (!nicknamec)
+ goto out;
}
SILC_LOG_DEBUG(("Resuming detached client"));
/* If the sender of this packet is server and we are router we need to
broadcast this packet to other routers in the network. */
if (server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_SERVER &&
+ idata->conn_type == SILC_CONN_SERVER &&
!(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
SILC_LOG_DEBUG(("Broadcasting received Resume Client packet"));
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
packet->type,
packet->flags | SILC_PACKET_FLAG_BROADCAST,
- buffer->data, buffer->len, FALSE);
- silc_server_backup_send(server, sock->user_data,
+ buffer->data, silc_buffer_len(buffer));
+ silc_server_backup_send(server, (SilcServerEntry)idata,
packet->type, packet->flags,
- packet->buffer->data, packet->buffer->len,
+ packet->buffer.data,
+ silc_buffer_len(&packet->buffer),
FALSE, TRUE);
}
detached_client->mode &= ~SILC_UMODE_DETACHED;
detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
detached_client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
- id_cache->expire = 0;
/* Check if anyone is watching this client */
if (server->server_type == SILC_ROUTER)
silc_schedule_task_del_by_context(server->schedule, detached_client);
/* Get the new owner of the resumed client */
- server_id = silc_id_str2id(packet->src_id, packet->src_id_len,
- packet->src_id_type);
- if (!server_id) {
- silc_free(client_id);
- return;
- }
+ if (!silc_id_str2id(packet->src_id, packet->src_id_len,
+ packet->src_id_type, &server_id, sizeof(server_id)))
+ goto out;
/* Get server entry */
server_entry = silc_idlist_find_server_by_id(server->global_list,
- server_id, TRUE, NULL);
+ &server_id, TRUE, NULL);
local = FALSE;
if (!server_entry) {
server_entry = silc_idlist_find_server_by_id(server->local_list,
- server_id, TRUE, NULL);
+ &server_id, TRUE, NULL);
local = TRUE;
- if (!server_entry) {
- silc_free(server_id);
- silc_free(client_id);
- return;
- }
+ if (!server_entry)
+ goto out;
}
if (server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_ROUTER &&
+ idata->conn_type == SILC_CONN_ROUTER &&
server_entry->server_type == SILC_ROUTER)
local = FALSE;
/* Change the client to correct list. */
if (!silc_idcache_del_by_context(server->local_list->clients,
- detached_client))
+ detached_client, NULL))
silc_idcache_del_by_context(server->global_list->clients,
- detached_client);
+ detached_client, NULL);
silc_idcache_add(local && server->server_type == SILC_ROUTER ?
server->local_list->clients :
server->global_list->clients, nicknamec,
- detached_client->id, detached_client, FALSE, NULL);
+ detached_client->id, detached_client);
/* Change the owner of the client */
detached_client->router = server_entry;
silc_server_channel_has_global(chl->channel);
silc_hash_table_list_reset(&htl);
}
-
- silc_free(server_id);
}
- silc_free(client_id);
+ out:
+ silc_packet_free(packet);
}
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2002 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/* Prototypes */
void silc_server_notify(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_notify_list(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_private_message(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_private_message_key(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_command_reply(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_channel_message(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_channel_key(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
SilcClientEntry silc_server_new_client(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
SilcServerEntry silc_server_new_server(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_new_channel(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_new_channel_list(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
-void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
- SilcPacketContext *packet);
-void silc_server_new_id_list(SilcServer server, SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
+void silc_server_new_id(SilcServer server, SilcPacketStream sock,
+ SilcPacket packet);
+void silc_server_new_id_list(SilcServer server, SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_remove_id(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_remove_id_list(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_key_agreement(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_connection_auth_request(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
-void silc_server_rekey(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_ftp(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_resume_client(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+ SilcPacketStream sock,
+ SilcPacket packet);
#endif
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
GNU General Public License for more details.
*/
-/*
- * Server packet routines to send packets.
- */
-/* $Id$ */
#include "serverincludes.h"
#include "server_internal.h"
-/* Routine that sends packet or marks packet to be sent. This is used
- directly only in special cases. Normal cases should use
- silc_server_packet_send. Returns < 0 error. */
-
-int silc_server_packet_send_real(SilcServer server,
- SilcSocketConnection sock,
- bool force_send)
-{
- int ret;
-
- /* If disconnecting, ignore the data */
- if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
- return -1;
-
- /* Send the packet */
- ret = silc_packet_send(sock, FALSE);
- if (ret != -2) {
- if (ret == -1) {
- SILC_SET_CONNECTION_FOR_INPUT(server->schedule, sock->sock);
- SILC_UNSET_OUTBUF_PENDING(sock);
- silc_buffer_clear(sock->outbuf);
-
- SILC_LOG_ERROR(("Error sending packet to connection "
- "%s:%d [%s]", sock->hostname, sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
-
- if (sock->user_data) {
- /* If backup then mark that resuming will not be allowed */
- if (server->server_type == SILC_ROUTER && !server->backup_router &&
- sock->type == SILC_SOCKET_TYPE_SERVER) {
- SilcServerEntry server_entry = sock->user_data;
- if (server_entry->server_type == SILC_BACKUP_ROUTER)
- server->backup_closed = TRUE;
- }
-
- silc_server_free_sock_user_data(server, sock, NULL);
- }
- SILC_SET_DISCONNECTING(sock);
- silc_server_close_connection(server, sock);
- return ret;
- }
-
- server->stat.packets_sent++;
- return ret;
- }
-
- /* Mark that there is some outgoing data available for this connection.
- This call sets the connection both for input and output (the input
- is set always and this call keeps the input setting, actually).
- Actual data sending is performed by silc_server_packet_process. */
- SILC_SET_CONNECTION_FOR_OUTPUT(server->schedule, sock->sock);
-
- /* Mark to socket that data is pending in outgoing buffer. This flag
- is needed if new data is added to the buffer before the earlier
- put data is sent to the network. */
- SILC_SET_OUTBUF_PENDING(sock);
+/* Send packet to remote connection */
- return 0;
-}
-
-/* Assembles a new packet to be sent out to network. This doesn't actually
- send the packet but creates the packet and fills the outgoing data
- buffer and marks the packet ready to be sent to network. However, If
- argument force_send is TRUE the packet is sent immediately and not put
- to queue. Normal case is that the packet is not sent immediately. */
-
-void silc_server_packet_send(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketType type,
- SilcPacketFlags flags,
- unsigned char *data,
- SilcUInt32 data_len,
- bool force_send)
+SilcBool silc_server_packet_send(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacketType type,
+ SilcPacketFlags flags,
+ unsigned char *data,
+ SilcUInt32 data_len)
{
- void *dst_id = NULL;
- SilcIdType dst_id_type = SILC_ID_NONE;
SilcIDListData idata;
if (!sock)
- return;
+ return FALSE;
- idata = (SilcIDListData)sock->user_data;
+ idata = silc_packet_get_context(sock);
- /* If disconnecting, ignore the data */
- if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
- return;
-
- /* If entry is disabled do not sent anything. Allow hearbeat and
- rekeys, though */
+ /* If entry is disabled do not sent anything. Allow hearbeat though */
if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED &&
- type != SILC_PACKET_HEARTBEAT && type != SILC_PACKET_REKEY &&
- type != SILC_PACKET_REKEY_DONE && type != SILC_PACKET_KEY_EXCHANGE_1
- && type != SILC_PACKET_KEY_EXCHANGE_2) ||
- (sock->user_data == server->id_entry)) {
+ type != SILC_PACKET_HEARTBEAT) ||
+ ((SilcServerEntry)idata == server->id_entry)) {
SILC_LOG_DEBUG(("Connection is disabled"));
- return;
+ return FALSE;
}
- /* Get data used in the packet sending, keys and stuff */
- switch(sock->type) {
- case SILC_SOCKET_TYPE_CLIENT:
- if (sock->user_data) {
- dst_id = ((SilcClientEntry)sock->user_data)->id;
- dst_id_type = SILC_ID_CLIENT;
- }
- break;
- case SILC_SOCKET_TYPE_SERVER:
- case SILC_SOCKET_TYPE_ROUTER:
- if (sock->user_data) {
- dst_id = ((SilcServerEntry)sock->user_data)->id;
- dst_id_type = SILC_ID_SERVER;
- }
- break;
- default:
- break;
- }
+ SILC_LOG_DEBUG(("Sending %s packet", silc_get_packet_name(type)));
- silc_server_packet_send_dest(server, sock, type, flags, dst_id,
- dst_id_type, data, data_len, force_send);
+ return silc_packet_send(sock, type, flags, (const unsigned char *)data,
+ data_len);
}
-/* Assembles a new packet to be sent out to network. This doesn't actually
- send the packet but creates the packet and fills the outgoing data
- buffer and marks the packet ready to be sent to network. However, If
- argument force_send is TRUE the packet is sent immediately and not put
- to queue. Normal case is that the packet is not sent immediately.
- Destination information is sent as argument for this function. */
-
-void silc_server_packet_send_dest(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketType type,
- SilcPacketFlags flags,
- void *dst_id,
- SilcIdType dst_id_type,
- unsigned char *data,
- SilcUInt32 data_len,
- bool force_send)
+/* Send packet to remote connection with specific destination ID. */
+
+SilcBool silc_server_packet_send_dest(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacketType type,
+ SilcPacketFlags flags,
+ void *dst_id,
+ SilcIdType dst_id_type,
+ unsigned char *data,
+ SilcUInt32 data_len)
{
- SilcPacketContext packetdata;
- const SilcBufferStruct packet;
SilcIDListData idata;
- SilcCipher cipher = NULL;
- SilcHmac hmac = NULL;
- SilcUInt32 sequence = 0;
- unsigned char *dst_id_data = NULL;
- SilcUInt32 dst_id_len = 0;
- int block_len = 0;
-
- /* If disconnecting, ignore the data */
- if (!sock || SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
- return;
- idata = (SilcIDListData)sock->user_data;
+ if (!sock)
+ return FALSE;
+
+ idata = silc_packet_get_context(sock);
- /* If entry is disabled do not sent anything. Allow hearbeat and
- rekeys, though */
+ /* If entry is disabled do not sent anything. Allow hearbeat though */
if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED &&
- type != SILC_PACKET_HEARTBEAT && type != SILC_PACKET_REKEY &&
- type != SILC_PACKET_REKEY_DONE && type != SILC_PACKET_KEY_EXCHANGE_1
- && type != SILC_PACKET_KEY_EXCHANGE_2) ||
- (sock->user_data == server->id_entry)) {
+ type != SILC_PACKET_HEARTBEAT) ||
+ ((SilcServerEntry)idata == server->id_entry)) {
SILC_LOG_DEBUG(("Connection is disabled"));
- return;
+ return FALSE;
}
- SILC_LOG_DEBUG(("Sending %s packet (forced=%s)",
- silc_get_packet_name(type), force_send ? "yes" : "no"));
-
- if (dst_id) {
- dst_id_data = silc_id_id2str(dst_id, dst_id_type);
- dst_id_len = silc_id_get_len(dst_id, dst_id_type);
- }
-
- if (idata) {
- cipher = idata->send_key;
- hmac = idata->hmac_send;
- sequence = idata->psn_send++;
- if (cipher)
- block_len = silc_cipher_get_block_len(cipher);
-
- /* Check for mandatory rekey */
- if (sequence == SILC_SERVER_REKEY_THRESHOLD)
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rekey_callback, sock, 0, 1,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
- }
-
- /* Set the packet context pointers */
- packetdata.type = type;
- packetdata.flags = flags;
- packetdata.src_id = silc_id_id2str(server->id, SILC_ID_SERVER);
- packetdata.src_id_len = silc_id_get_len(server->id, SILC_ID_SERVER);
- packetdata.src_id_type = SILC_ID_SERVER;
- packetdata.dst_id = dst_id_data;
- packetdata.dst_id_len = dst_id_len;
- packetdata.dst_id_type = dst_id_type;
- data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
- packetdata.src_id_len +
- packetdata.dst_id_len));
- packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
- packetdata.src_id_len + dst_id_len;
- if (type == SILC_PACKET_CONNECTION_AUTH)
- SILC_PACKET_PADLEN_MAX(packetdata.truelen, block_len, packetdata.padlen);
- else
- SILC_PACKET_PADLEN(packetdata.truelen, block_len, packetdata.padlen);
-
- /* Create the outgoing packet */
- if (!silc_packet_assemble(&packetdata, NULL, cipher, hmac, sock,
- data, data_len, (const SilcBuffer)&packet)) {
- SILC_LOG_ERROR(("Cannot assemble packet"));
- goto out;
- }
-
- /* Encrypt the packet */
- silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet, packet.len);
-
- SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence, packet.len),
- packet.data, packet.len);
-
- /* Now actually send the packet */
- silc_server_packet_send_real(server, sock, force_send);
+ SILC_LOG_DEBUG(("Sending %s packet", silc_get_packet_name(type)));
- out:
- silc_free(packetdata.src_id);
- silc_free(packetdata.dst_id);
+ return silc_packet_send_ext(sock, type, flags, 0, NULL, dst_id_type, dst_id,
+ (const unsigned char *)data, data_len,
+ NULL, NULL);
}
-/* Assembles a new packet to be sent out to network. This doesn't actually
- send the packet but creates the packet and fills the outgoing data
- buffer and marks the packet ready to be sent to network. However, If
- argument force_send is TRUE the packet is sent immediately and not put
- to queue. Normal case is that the packet is not sent immediately.
- The source and destination information is sent as argument for this
- function. */
+/* Send packet to remote connection with specific source and destination
+ IDs. */
-void silc_server_packet_send_srcdest(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketType type,
- SilcPacketFlags flags,
- void *src_id,
- SilcIdType src_id_type,
- void *dst_id,
- SilcIdType dst_id_type,
- unsigned char *data,
- SilcUInt32 data_len,
- bool force_send)
+SilcBool silc_server_packet_send_srcdest(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacketType type,
+ SilcPacketFlags flags,
+ void *src_id,
+ SilcIdType src_id_type,
+ void *dst_id,
+ SilcIdType dst_id_type,
+ unsigned char *data,
+ SilcUInt32 data_len)
{
- SilcPacketContext packetdata;
- const SilcBufferStruct packet;
SilcIDListData idata;
- SilcCipher cipher = NULL;
- SilcHmac hmac = NULL;
- SilcUInt32 sequence = 0;
- unsigned char *dst_id_data = NULL;
- SilcUInt32 dst_id_len = 0;
- unsigned char *src_id_data = NULL;
- SilcUInt32 src_id_len = 0;
- int block_len = 0;
-
- SILC_LOG_DEBUG(("Sending %s packet", silc_get_packet_name(type)));
if (!sock)
- return;
+ return FALSE;
- /* Get data used in the packet sending, keys and stuff */
- idata = (SilcIDListData)sock->user_data;
+ idata = silc_packet_get_context(sock);
- /* If entry is disabled do not sent anything. Allow hearbeat and
- rekeys, though */
+ /* If entry is disabled do not sent anything. Allow hearbeat though */
if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED &&
- type != SILC_PACKET_HEARTBEAT && type != SILC_PACKET_REKEY &&
- type != SILC_PACKET_REKEY_DONE && type != SILC_PACKET_KEY_EXCHANGE_1
- && type != SILC_PACKET_KEY_EXCHANGE_2) ||
- (sock->user_data == server->id_entry)) {
+ type != SILC_PACKET_HEARTBEAT) ||
+ ((SilcServerEntry)idata == server->id_entry)) {
SILC_LOG_DEBUG(("Connection is disabled"));
- return;
- }
-
- if (idata) {
- cipher = idata->send_key;
- hmac = idata->hmac_send;
- sequence = idata->psn_send++;
- block_len = silc_cipher_get_block_len(cipher);
-
- /* Check for mandatory rekey */
- if (sequence == SILC_SERVER_REKEY_THRESHOLD)
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rekey_callback, sock, 0, 1,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
- }
-
- if (dst_id) {
- dst_id_data = silc_id_id2str(dst_id, dst_id_type);
- dst_id_len = silc_id_get_len(dst_id, dst_id_type);
- }
-
- if (src_id) {
- src_id_data = silc_id_id2str(src_id, src_id_type);
- src_id_len = silc_id_get_len(src_id, src_id_type);
- }
-
- /* Set the packet context pointers */
- packetdata.type = type;
- packetdata.flags = flags;
- packetdata.src_id = src_id_data;
- packetdata.src_id_len = src_id_len;
- packetdata.src_id_type = src_id_type;
- packetdata.dst_id = dst_id_data;
- packetdata.dst_id_len = dst_id_len;
- packetdata.dst_id_type = dst_id_type;
- data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
- packetdata.src_id_len +
- dst_id_len));
- packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
- packetdata.src_id_len + dst_id_len;
- SILC_PACKET_PADLEN(packetdata.truelen, block_len, packetdata.padlen);
-
- /* Create the outgoing packet */
- if (!silc_packet_assemble(&packetdata, NULL, cipher, hmac, sock, data,
- data_len, (const SilcBuffer)&packet)) {
- SILC_LOG_ERROR(("Cannot assemble packe"));
- goto out;
+ return FALSE;
}
- /* Encrypt the packet */
- silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet, packet.len);
-
- SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence, packet.len),
- packet.data, packet.len);
-
- /* Now actually send the packet */
- silc_server_packet_send_real(server, sock, force_send);
+ SILC_LOG_DEBUG(("Sending %s packet", silc_get_packet_name(type)));
- out:
- silc_free(packetdata.src_id);
- silc_free(packetdata.dst_id);
+ return silc_packet_send_ext(sock, type, flags, src_id_type, src_id,
+ dst_id_type, dst_id,
+ (const unsigned char *)data, data_len,
+ NULL, NULL);
}
/* Broadcast received packet to our primary route. This function is used
that the broadcast flag from the packet is checked before calling this
function. This does not test or set the broadcast flag. */
-void silc_server_packet_broadcast(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+SilcBool silc_server_packet_broadcast(SilcServer server,
+ SilcPacketStream primary_route,
+ SilcPacket packet)
{
- SilcBuffer buffer = packet->buffer;
- SilcIDListData idata;
- void *id;
+ SilcServerID src_id, dst_id;
- if (!sock)
- return;
+ if (!primary_route)
+ return FALSE;
SILC_LOG_DEBUG(("Broadcasting received broadcast packet"));
- /* If the packet is originated from our primary route we are
- not allowed to send the packet. */
- id = silc_id_str2id(packet->src_id, packet->src_id_len, packet->src_id_type);
- if (id && !SILC_ID_SERVER_COMPARE(id, server->router->id)) {
- const SilcBufferStruct p;
-
- idata = (SilcIDListData)sock->user_data;
-
- silc_buffer_push(buffer, buffer->data - buffer->head);
- if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send,
- (const SilcBuffer)&p)) {
- SILC_LOG_ERROR(("Cannot send packet"));
- silc_free(id);
- return;
- }
- silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
- silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++,
- (SilcBuffer)&p, p.len);
-
- SILC_LOG_HEXDUMP(("Broadcasted packet (%d), len %d", idata->psn_send - 1,
- p.len), p.data, p.len);
-
- /* Now actually send the packet */
- silc_server_packet_send_real(server, sock, TRUE);
- silc_free(id);
-
- /* Check for mandatory rekey */
- if (idata->psn_send == SILC_SERVER_REKEY_THRESHOLD)
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rekey_callback, sock, 0, 1,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
- return;
+ if (!silc_id_str2id(packet->src_id, packet->src_id_len, packet->src_id_type,
+ &src_id, sizeof(src_id)))
+ return FALSE;
+ if (!silc_id_str2id(packet->dst_id, packet->dst_id_len, packet->dst_id_type,
+ &dst_id, sizeof(dst_id)))
+ return FALSE;
+
+ /* If the packet is originated from our primary route we are not allowed
+ to send the packet. */
+ if (SILC_ID_SERVER_COMPARE(&src_id, server->router->id)) {
+ SILC_LOG_DEBUG(("Will not broadcast to primary route since it is the "
+ "original sender of this packet"));
+ return FALSE;
}
- SILC_LOG_DEBUG(("Will not broadcast to primary route since it is the "
- "original sender of this packet"));
- silc_free(id);
+ /* Send the packet */
+ return silc_server_packet_send_srcdest(server, primary_route, packet->type,
+ packet->flags, &src_id,
+ SILC_ID_SERVER, &dst_id,
+ SILC_ID_SERVER,
+ packet->buffer.data,
+ silc_buffer_len(&packet->buffer));
}
/* Routes received packet to `sock'. This is used to route the packets that
router receives but are not destined to it. */
-void silc_server_packet_route(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+SilcBool silc_server_packet_route(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacket packet)
{
- SilcBuffer buffer = packet->buffer;
- const SilcBufferStruct p;
- SilcIDListData idata;
-
- SILC_LOG_DEBUG(("Routing received packet"));
-
- idata = (SilcIDListData)sock->user_data;
-
- silc_buffer_push(buffer, buffer->data - buffer->head);
- if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send,
- (const SilcBuffer)&p)) {
- SILC_LOG_ERROR(("Cannot send packet"));
- return;
- }
- silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
- silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++,
- (SilcBuffer)&p, p.len);
-
- SILC_LOG_HEXDUMP(("Routed packet (%d), len %d", idata->psn_send - 1,
- p.len), p.data, p.len);
-
- /* Now actually send the packet */
- silc_server_packet_send_real(server, sock, TRUE);
-
- /* Check for mandatory rekey */
- if (idata->psn_send == SILC_SERVER_REKEY_THRESHOLD)
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rekey_callback, sock, 0, 1,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ SilcID src_id, dst_id;
+
+ if (!silc_id_str2id2(packet->src_id, packet->src_id_len, packet->src_id_type,
+ &src_id))
+ return FALSE;
+ if (!silc_id_str2id2(packet->dst_id, packet->dst_id_len, packet->dst_id_type,
+ &dst_id))
+ return FALSE;
+
+ return silc_server_packet_send_srcdest(server, sock, packet->type,
+ packet->flags,
+ SILC_ID_GET_ID(src_id),
+ src_id.type,
+ SILC_ID_GET_ID(dst_id),
+ dst_id.type,
+ packet->buffer.data,
+ silc_buffer_len(&packet->buffer));
}
/* This routine can be used to send a packet to table of clients provided
SilcHashTable clients,
SilcPacketType type,
SilcPacketFlags flags,
- bool route,
+ SilcBool route,
unsigned char *data,
- SilcUInt32 data_len,
- bool force_send)
+ SilcUInt32 data_len)
{
- SilcSocketConnection sock = NULL;
+ SilcPacketStream sock = NULL;
+ SilcIDListData idata;
SilcHashTableList htl;
SilcClientEntry client = NULL;
SilcServerEntry *routed = NULL;
SilcUInt32 routed_count = 0;
- bool gone = FALSE;
+ SilcBool gone = FALSE;
int k;
if (!silc_hash_table_count(clients))
continue;
/* Route only once to router */
- sock = (SilcSocketConnection)client->router->connection;
- if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ sock = client->router->connection;
+ idata = silc_packet_get_context(sock);
+ if (idata->conn_type == SILC_CONN_ROUTER) {
if (gone)
continue;
gone = TRUE;
/* Send the packet */
silc_server_packet_send_dest(server, sock, type, flags,
client->router->id, SILC_ID_SERVER,
- data, data_len, force_send);
+ data, data_len);
/* Mark this route routed already */
routed = silc_realloc(routed, sizeof(*routed) * (routed_count + 1));
continue;
/* Send to locally connected client */
- sock = (SilcSocketConnection)client->connection;
+ sock = client->connection;
if (!sock)
continue;
silc_server_packet_send_dest(server, sock, type, flags,
client->id, SILC_ID_CLIENT,
- data, data_len, force_send);
+ data, data_len);
}
silc_hash_table_list_reset(&htl);
silc_free(routed);
}
-/* Internal routine to actually create the channel packet and send it
- to network. This is common function in channel message sending. If
- `channel_message' is TRUE this encrypts the message as it is strictly
- a channel message. If FALSE normal encryption process is used. */
-
-static void
-silc_server_packet_send_to_channel_real(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet,
- SilcCipher cipher,
- SilcHmac hmac,
- SilcUInt32 sequence,
- unsigned char *data,
- SilcUInt32 data_len,
- bool channel_message,
- bool force_send)
-{
- int block_len;
- const SilcBufferStruct p;
-
- if (!sock)
- return;
-
- data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
- packet->src_id_len +
- packet->dst_id_len));
- packet->truelen = data_len + SILC_PACKET_HEADER_LEN +
- packet->src_id_len + packet->dst_id_len;
-
- block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
- if (channel_message)
- SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
- packet->src_id_len +
- packet->dst_id_len), block_len, packet->padlen);
- else
- SILC_PACKET_PADLEN(packet->truelen, block_len, packet->padlen);
-
- /* Put the data to buffer, assemble and encrypt the packet. The packet
- is encrypted with normal session key shared with the client, unless
- the `channel_message' is TRUE. */
- if (!silc_packet_assemble(packet, NULL, cipher, hmac, sock, data,
- data_len, (const SilcBuffer)&p)) {
- SILC_LOG_ERROR(("Cannot assemble packet"));
- return;
- }
-
- if (channel_message)
- silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p,
- SILC_PACKET_HEADER_LEN + packet->src_id_len +
- packet->dst_id_len + packet->padlen);
- else
- silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p, p.len);
-
- SILC_LOG_HEXDUMP(("Channel packet (%d), len %d", sequence, p.len),
- p.data, p.len);
-
- /* Now actually send the packet */
- silc_server_packet_send_real(server, sock, force_send);
-}
-
/* This routine is used by the server to send packets to channel. The
packet sent with this function is distributed to all clients on
the channel. Usually this is used to send notify messages to the
packet is not sent clients, only servers. */
void silc_server_packet_send_to_channel(SilcServer server,
- SilcSocketConnection sender,
+ SilcPacketStream sender,
SilcChannelEntry channel,
SilcPacketType type,
- bool route,
- bool send_to_clients,
+ SilcBool route,
+ SilcBool send_to_clients,
unsigned char *data,
- SilcUInt32 data_len,
- bool force_send)
+ SilcUInt32 data_len)
{
- SilcSocketConnection sock = NULL;
- SilcPacketContext packetdata;
+ SilcPacketStream sock = NULL;
SilcClientEntry client = NULL;
SilcServerEntry *routed = NULL;
SilcChannelClientEntry chl;
SilcHashTableList htl;
SilcIDListData idata;
SilcUInt32 routed_count = 0;
- bool gone = FALSE;
+ SilcBool gone = FALSE;
int k;
/* This doesn't send channel message packets */
assert(type != SILC_PACKET_CHANNEL_MESSAGE);
- /* Set the packet context pointers. */
- packetdata.flags = 0;
- packetdata.type = type;
- packetdata.src_id = silc_id_id2str(server->id, SILC_ID_SERVER);
- packetdata.src_id_len = silc_id_get_len(server->id, SILC_ID_SERVER);
- packetdata.src_id_type = SILC_ID_SERVER;
- packetdata.dst_id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
- packetdata.dst_id_type = SILC_ID_CHANNEL;
-
/* If there are global users in the channel we will send the message
first to our router for further routing. */
if (route && server->server_type != SILC_ROUTER && !server->standalone &&
channel->global_users) {
- SilcServerEntry router;
-
- /* Get data used in packet header encryption, keys and stuff. */
- router = server->router;
- sock = (SilcSocketConnection)router->connection;
- idata = (SilcIDListData)router;
-
+ sock = server->router->connection;
if (sock != sender) {
SILC_LOG_DEBUG(("Sending packet to router for routing"));
- silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key,
- idata->hmac_send,
- idata->psn_send++,
- data, data_len, FALSE,
- force_send);
+ silc_server_packet_send_dest(server, sock, type, 0, channel->id,
+ SILC_ID_CHANNEL, data, data_len);
}
}
continue;
/* Get data used in packet header encryption, keys and stuff. */
- sock = (SilcSocketConnection)client->router->connection;
+ sock = client->router->connection;
idata = (SilcIDListData)client->router;
if (sender && sock == sender)
/* Route only once to router. Protocol prohibits sending channel
messages to more than one router. */
- if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ if (idata->conn_type == SILC_CONN_ROUTER) {
if (gone)
continue;
gone = TRUE;
(unsigned char *)""));
/* Send the packet */
- silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key,
- idata->hmac_send,
- idata->psn_send++,
- data, data_len, FALSE,
- force_send);
+ silc_server_packet_send_dest(server, sock, type, 0, channel->id,
+ SILC_ID_CHANNEL, data, data_len);
/* Mark this route routed already */
routed[routed_count++] = client->router;
/* Send to locally connected client */
/* Get data used in packet header encryption, keys and stuff. */
- sock = (SilcSocketConnection)client->connection;
- idata = (SilcIDListData)client;
-
+ sock = client->connection;
if (!sock || (sender && sock == sender))
continue;
(unsigned char *)""));
/* Send the packet */
- silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key,
- idata->hmac_send,
- idata->psn_send++,
- data, data_len, FALSE,
- force_send);
+ silc_server_packet_send_dest(server, sock, type, 0, channel->id,
+ SILC_ID_CHANNEL, data, data_len);
}
silc_hash_table_list_reset(&htl);
out:
silc_free(routed);
- silc_free(packetdata.src_id);
- silc_free(packetdata.dst_id);
}
/* This checks whether the relayed packet came from router. If it did
then we'll need to encrypt it with the channel key. This is called
from the silc_server_packet_relay_to_channel. */
-static bool
+static SilcBool
silc_server_packet_relay_to_channel_encrypt(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sender,
SilcChannelEntry channel,
unsigned char *data,
unsigned int data_len)
{
+ SilcIDListData idata;
SilcUInt32 mac_len, iv_len;
unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
SilcUInt16 totlen, len;
+ SilcID src_id, dst_id;
+
+ idata = silc_packet_get_context(sender);
/* If we are router and the packet came from router and private key
has not been set for the channel then we must encrypt the packet
router which sent it. This is so, because cells does not share the
same channel key. */
if (server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_ROUTER &&
+ idata->conn_type == SILC_CONN_ROUTER &&
!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY) && channel->key) {
/* If we are backup router and remote is our primary router and
we are currently doing backup resuming protocol we must not
re-encrypt message with session key. */
- if (server->backup_router && SILC_SERVER_IS_BACKUP(sock) &&
- SILC_PRIMARY_ROUTE(server) == sock)
+ if (server->backup_router && idata->sconn->backup_resuming &&
+ SILC_PRIMARY_ROUTE(server) == sender)
return TRUE;
mac_len = silc_hmac_len(channel->hmac);
- iv_len = silc_cipher_get_block_len(channel->channel_key);
+ iv_len = silc_cipher_get_block_len(channel->send_key);
if (data_len <= mac_len + iv_len) {
SILC_LOG_WARNING(("Corrupted channel message, cannot relay it"));
}
memcpy(iv, data + (data_len - iv_len - mac_len), iv_len);
- silc_message_payload_encrypt(data, totlen, data_len - mac_len,
- iv, iv_len, channel->channel_key,
- channel->hmac);
+
+ src_id.type = SILC_ID_SERVER;
+ src_id.u.server_id = *((SilcServerEntry)idata)->id;
+ dst_id.type = SILC_ID_CHANNEL;
+ dst_id.u.channel_id = *channel->id;
+
+ return silc_message_payload_encrypt(data, totlen, data_len - mac_len,
+ iv, &src_id, &dst_id,
+ channel->send_key, channel->hmac);
}
return TRUE;
packet will be untouched. */
void silc_server_packet_relay_to_channel(SilcServer server,
- SilcSocketConnection sender_sock,
+ SilcPacketStream sender_sock,
SilcChannelEntry channel,
void *sender_id,
SilcIdType sender_type,
SilcClientEntry sender_entry,
unsigned char *data,
- SilcUInt32 data_len,
- bool force_send)
+ SilcUInt32 data_len)
{
- SilcSocketConnection sock = NULL;
- SilcPacketContext packetdata;
+ SilcPacketStream sock = NULL;
SilcClientEntry client = NULL;
SilcServerEntry *routed = NULL;
SilcChannelClientEntry chl, chl_sender;
SilcUInt32 routed_count = 0;
SilcIDListData idata;
SilcHashTableList htl;
- bool gone = FALSE;
+ SilcBool gone = FALSE;
int k;
if (!silc_server_client_on_channel(sender_entry, channel, &chl_sender))
SILC_LOG_DEBUG(("Relaying packet to channel %s", channel->channel_name));
- /* This encrypts the packet, if needed. It will be encrypted if
+ /* This encrypts the message, if needed. It will be encrypted if
it came from the router thus it needs to be encrypted with the
channel key. If the channel key does not exist, then we know we
don't have a single local user on the channel. */
data_len))
return;
- /* Set the packet context pointers. */
- packetdata.flags = 0;
- packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
- packetdata.src_id = silc_id_id2str(sender_id, sender_type);
- packetdata.src_id_len = silc_id_get_len(sender_id, sender_type);
- packetdata.src_id_type = sender_type;
- packetdata.dst_id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
- packetdata.dst_id_type = SILC_ID_CHANNEL;
-
/* If there are global users in the channel we will send the message
first to our router for further routing. */
if (server->server_type != SILC_ROUTER && !server->standalone &&
SilcServerEntry router = server->router;
/* Check that the sender is not our router. */
- if (sender_sock != (SilcSocketConnection)router->connection) {
-
- /* Get data used in packet header encryption, keys and stuff. */
- sock = (SilcSocketConnection)router->connection;
- idata = (SilcIDListData)router;
-
+ if (sender_sock != router->connection) {
SILC_LOG_DEBUG(("Sending message to router for routing"));
-
- silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key,
- idata->hmac_send,
- idata->psn_send++,
- data, data_len, TRUE,
- force_send);
+ sock = router->connection;
+ silc_server_packet_send_srcdest(server, sock,
+ SILC_PACKET_CHANNEL_MESSAGE, 0,
+ sender_id, sender_type,
+ channel->id, SILC_ID_CHANNEL,
+ data, data_len);
}
}
continue;
/* Get data used in packet header encryption, keys and stuff. */
- sock = (SilcSocketConnection)client->router->connection;
+ sock = client->router->connection;
idata = (SilcIDListData)client->router;
/* Check if the sender socket is the same as this client's router
if (sender_sock && sock == sender_sock)
continue;
- SILC_LOG_DEBUG(("Relaying packet to client ID(%s) %s (%s)",
- silc_id_render(client->id, SILC_ID_CLIENT),
- sock->hostname, sock->ip));
+ SILC_LOG_DEBUG(("Relaying packet to client ID(%s)",
+ silc_id_render(client->id, SILC_ID_CLIENT)));
/* Mark this route routed already. */
routed[routed_count++] = client->router;
- if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ if (idata->conn_type == SILC_CONN_ROUTER) {
/* The remote connection is router then we'll decrypt the
channel message and re-encrypt it with the session key shared
between us and the remote router. This is done because the
/* If we are backup router and remote is our primary router and
we are currently doing backup resuming protocol we must not
re-encrypt message with session key. */
- if (server->backup_router && SILC_SERVER_IS_BACKUP(sock) &&
+ if (server->backup_router && idata->sconn->backup_resuming &&
SILC_PRIMARY_ROUTE(server) == sock) {
- silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key,
- idata->hmac_send,
- idata->psn_send++,
- data, data_len, TRUE,
- force_send);
+ silc_server_packet_send_srcdest(server, sock,
+ SILC_PACKET_CHANNEL_MESSAGE, 0,
+ sender_id, sender_type,
+ channel->id, SILC_ID_CHANNEL,
+ data, data_len);
continue;
}
/* If private key mode is not set then decrypt the packet
and re-encrypt it */
if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY) &&
- channel->channel_key) {
- unsigned char tmp[SILC_PACKET_MAX_LEN];
+ channel->receive_key) {
+ unsigned char tmp[SILC_PACKET_MAX_LEN], sid[32], rid[32];
+ SilcUInt32 sid_len, rid_len;
if (data_len > SILC_PACKET_MAX_LEN)
data_len = SILC_PACKET_MAX_LEN;
memcpy(tmp, data, data_len);
/* Decrypt the channel message (we don't check the MAC) */
+ silc_id_id2str(sender_id, sender_type, sid, sizeof(sid), &sid_len);
+ silc_id_id2str(channel->id, SILC_ID_CHANNEL, rid, sizeof(rid),
+ &rid_len);
silc_message_payload_decrypt(tmp, data_len, FALSE, FALSE,
- channel->channel_key,
- channel->hmac, FALSE);
+ channel->receive_key,
+ channel->hmac, sid, sid_len,
+ rid, rid_len, FALSE);
/* Now re-encrypt and send it to the router */
silc_server_packet_send_srcdest(server, sock,
SILC_PACKET_CHANNEL_MESSAGE, 0,
sender_id, sender_type,
channel->id, SILC_ID_CHANNEL,
- tmp, data_len, force_send);
+ tmp, data_len);
} else {
/* Private key mode is set, we don't have the channel key, so
just re-encrypt the entire packet and send it to the router. */
SILC_PACKET_CHANNEL_MESSAGE, 0,
sender_id, sender_type,
channel->id, SILC_ID_CHANNEL,
- data, data_len, force_send);
+ data, data_len);
}
} else {
/* Send the packet to normal server */
- silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key,
- idata->hmac_send,
- idata->psn_send++,
- data, data_len, TRUE,
- force_send);
+ silc_server_packet_send_srcdest(server, sock,
+ SILC_PACKET_CHANNEL_MESSAGE, 0,
+ sender_id, sender_type,
+ channel->id, SILC_ID_CHANNEL,
+ data, data_len);
}
continue;
continue;
/* Get data used in packet header encryption, keys and stuff. */
- sock = (SilcSocketConnection)client->connection;
- idata = (SilcIDListData)client;
-
+ sock = client->connection;
if (!sock || (sender_sock && sock == sender_sock))
continue;
- SILC_LOG_DEBUG(("Sending packet to client ID(%s) %s (%s)",
- silc_id_render(client->id, SILC_ID_CLIENT),
- sock->hostname, sock->ip));
+ SILC_LOG_DEBUG(("Sending packet to client ID(%s)",
+ silc_id_render(client->id, SILC_ID_CLIENT)));
/* Send the packet */
- silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key,
- idata->hmac_send,
- idata->psn_send++,
- data, data_len, TRUE,
- force_send);
+ silc_server_packet_send_srcdest(server, sock,
+ SILC_PACKET_CHANNEL_MESSAGE, 0,
+ sender_id, sender_type,
+ channel->id, SILC_ID_CHANNEL,
+ data, data_len);
}
silc_hash_table_list_reset(&htl);
silc_free(routed);
- silc_free(packetdata.src_id);
- silc_free(packetdata.dst_id);
}
/* This function is used to send packets strictly to all local clients
SilcPacketType type,
SilcPacketFlags flags,
unsigned char *data,
- SilcUInt32 data_len,
- bool force_send)
+ SilcUInt32 data_len)
{
SilcChannelClientEntry chl;
SilcHashTableList htl;
- SilcSocketConnection sock = NULL;
+ SilcPacketStream sock = NULL;
SILC_LOG_DEBUG(("Send packet to local clients on channel %s",
channel->channel_name));
/* Send the packet to the client */
silc_server_packet_send_dest(server, sock, type, flags, chl->client->id,
- SILC_ID_CLIENT, data, data_len,
- force_send);
+ SILC_ID_CLIENT, data, data_len);
}
}
silc_hash_table_list_reset(&htl);
}
-/* Routine used to send (relay, route) private messages to some destination.
- If the private message key does not exist then the message is re-encrypted,
- otherwise we just pass it along. This really is not used to send new
- private messages (as server does not send them) but to relay received
- private messages. */
-
-void silc_server_send_private_message(SilcServer server,
- SilcSocketConnection dst_sock,
- SilcCipher cipher,
- SilcHmac hmac,
- SilcUInt32 sequence,
- SilcPacketContext *packet)
-{
- SilcBuffer buffer = packet->buffer;
- const SilcBufferStruct p;
-
- silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len
- + packet->dst_id_len + packet->padlen);
- if (!silc_packet_send_prepare(dst_sock, 0, 0, buffer->len, hmac,
- (const SilcBuffer)&p)) {
- SILC_LOG_ERROR(("Cannot send packet"));
- return;
- }
- silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
-
- /* Re-encrypt and send if private messge key does not exist */
- if (!(packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY)) {
- /* Re-encrypt packet */
- silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p, buffer->len);
- } else {
- /* Key exist so encrypt just header and send it */
- silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p,
- SILC_PACKET_HEADER_LEN + packet->src_id_len +
- packet->dst_id_len + packet->padlen);
- }
-
- /* Send the packet */
- silc_server_packet_send_real(server, dst_sock, FALSE);
-
- /* Check for mandatory rekey */
- if (sequence == SILC_SERVER_REKEY_THRESHOLD)
- silc_schedule_task_add(server->schedule, dst_sock->sock,
- silc_server_rekey_callback, dst_sock, 0, 1,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-}
-
/* Sends current motd to client */
void silc_server_send_motd(SilcServer server,
- SilcSocketConnection sock)
+ SilcPacketStream sock)
{
char *motd, *motd_file = NULL;
SilcUInt32 motd_len;
implications. */
void silc_server_send_error(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
const char *fmt, ...)
{
va_list ap;
va_end(ap);
silc_server_packet_send(server, sock, SILC_PACKET_ERROR, 0,
- buf, strlen(buf), FALSE);
+ buf, strlen(buf));
}
/* Sends notify message. If format is TRUE the variable arguments are
in the argument list must be { argument data, argument length }. */
void silc_server_send_notify(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcNotifyType type,
SilcUInt32 argc, ...)
{
packet = silc_notify_payload_encode(type, argc, ap);
silc_server_packet_send(server, sock, SILC_PACKET_NOTIFY,
broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
- packet->data, packet->len, FALSE);
+ packet->data, silc_buffer_len(packet));
/* Send to backup routers if this is being broadcasted to primary
router. The silc_server_backup_send checks further whether to
if ((broadcast && sock && sock == SILC_PRIMARY_ROUTE(server)) ||
(broadcast && !sock && !SILC_PRIMARY_ROUTE(server)))
silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
- packet->data, packet->len, FALSE, TRUE);
+ packet->data, silc_buffer_len(packet),
+ FALSE, TRUE);
silc_buffer_free(packet);
va_end(ap);
Payloads. */
void silc_server_send_notify_args(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcNotifyType type,
SilcUInt32 argc,
SilcBuffer args)
packet = silc_notify_payload_encode_args(type, argc, args);
silc_server_packet_send(server, sock, SILC_PACKET_NOTIFY,
broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
- packet->data, packet->len, FALSE);
+ packet->data, silc_buffer_len(packet));
silc_buffer_free(packet);
}
`old_id' with the `new_id'. */
void silc_server_send_notify_channel_change(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelID *old_id,
SilcChannelID *new_id)
{
silc_server_send_notify(server, sock, broadcast,
SILC_NOTIFY_TYPE_CHANNEL_CHANGE,
- 2, idp1->data, idp1->len, idp2->data, idp2->len);
+ 2, idp1->data, silc_buffer_len(idp1),
+ idp2->data, silc_buffer_len(idp2));
silc_buffer_free(idp1);
silc_buffer_free(idp2);
}
`old_id' with the `new_id'. */
void silc_server_send_notify_nick_change(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcClientID *old_id,
SilcClientID *new_id,
const char *nickname)
silc_server_send_notify(server, sock, broadcast,
SILC_NOTIFY_TYPE_NICK_CHANGE,
- 3, idp1->data, idp1->len, idp2->data, idp2->len,
+ 3, idp1->data, silc_buffer_len(idp1),
+ idp2->data, silc_buffer_len(idp2),
nickname, nickname ? strlen(nickname) : 0);
silc_buffer_free(idp1);
silc_buffer_free(idp2);
has joined to the `channel'. */
void silc_server_send_notify_join(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id)
{
idp1 = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
idp2 = silc_id_payload_encode((void *)channel->id, SILC_ID_CHANNEL);
silc_server_send_notify(server, sock, broadcast, SILC_NOTIFY_TYPE_JOIN,
- 2, idp1->data, idp1->len,
- idp2->data, idp2->len);
+ 2, idp1->data, silc_buffer_len(idp1),
+ idp2->data, silc_buffer_len(idp2));
silc_buffer_free(idp1);
silc_buffer_free(idp2);
}
`channel'. The Notify packet is always destined to the channel. */
void silc_server_send_notify_leave(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id)
{
idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
SILC_ID_CHANNEL, SILC_NOTIFY_TYPE_LEAVE,
- 1, idp->data, idp->len);
+ 1, idp->data, silc_buffer_len(idp));
silc_buffer_free(idp);
}
the channel. */
void silc_server_send_notify_cmode(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
SilcUInt32 mode_mask,
void *id, SilcIdType id_type,
idp = silc_id_payload_encode((void *)id, id_type);
SILC_PUT32_MSB(mode_mask, mode);
if (founder_key)
- fkey = silc_pkcs_public_key_payload_encode(founder_key);
+ fkey = silc_public_key_payload_encode(founder_key);
if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
SILC_PUT32_MSB(channel->user_limit, ulimit);
silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
SILC_ID_CHANNEL, SILC_NOTIFY_TYPE_CMODE_CHANGE,
- 8, idp->data, idp->len,
+ 8, idp->data, silc_buffer_len(idp),
mode, 4,
cipher, cipher ? strlen(cipher) : 0,
hmac, hmac ? strlen(hmac) : 0,
passphrase, passphrase ?
strlen(passphrase) : 0,
- fkey ? fkey->data : NULL, fkey ? fkey->len : 0,
+ fkey ? fkey->data : NULL,
+ fkey ? silc_buffer_len(fkey) : 0,
channel_pubkeys ? channel_pubkeys->data : NULL,
- channel_pubkeys ? channel_pubkeys->len : 0,
+ channel_pubkeys ?
+ silc_buffer_len(channel_pubkeys) : 0,
mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
ulimit : NULL,
mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
destined to the channel. */
void silc_server_send_notify_cumode(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
SilcUInt32 mode_mask,
void *id, SilcIdType id_type,
idp2 = silc_id_payload_encode((void *)target, SILC_ID_CLIENT);
SILC_PUT32_MSB(mode_mask, mode);
if (founder_key)
- fkey = silc_pkcs_public_key_payload_encode(founder_key);
+ fkey = silc_public_key_payload_encode(founder_key);
silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
SILC_ID_CHANNEL,
SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
- idp1->data, idp1->len,
+ idp1->data, silc_buffer_len(idp1),
mode, 4,
- idp2->data, idp2->len,
- fkey ? fkey->data : NULL, fkey ? fkey->len : 0);
+ idp2->data, silc_buffer_len(idp2),
+ fkey ? fkey->data : NULL,
+ fkey ? silc_buffer_len(fkey) : 0);
silc_buffer_free(fkey);
silc_buffer_free(idp1);
silc_buffer_free(idp2);
client. The `message may be NULL. */
void silc_server_send_notify_signoff(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcClientID *client_id,
const char *message)
{
idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
silc_server_send_notify(server, sock, broadcast,
SILC_NOTIFY_TYPE_SIGNOFF,
- message ? 2 : 1, idp->data, idp->len,
+ message ? 2 : 1, idp->data, silc_buffer_len(idp),
message, message ? strlen(message): 0);
silc_buffer_free(idp);
}
between routers. */
void silc_server_send_notify_topic_set(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
void *id, SilcIdType id_type,
char *topic)
(void *)channel->id, SILC_ID_CHANNEL,
SILC_NOTIFY_TYPE_TOPIC_SET,
topic ? 2 : 1,
- idp->data, idp->len,
+ idp->data, silc_buffer_len(idp),
topic, topic ? strlen(topic) : 0);
silc_buffer_free(idp);
}
traffic. */
void silc_server_send_notify_kicked(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
SilcClientID *kicker,
idp2 = silc_id_payload_encode((void *)kicker, SILC_ID_CLIENT);
silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
SILC_ID_CHANNEL, SILC_NOTIFY_TYPE_KICKED, 3,
- idp1->data, idp1->len,
+ idp1->data, silc_buffer_len(idp1),
comment, comment ? strlen(comment) : 0,
- idp2->data, idp2->len);
+ idp2->data, silc_buffer_len(idp2));
silc_buffer_free(idp1);
silc_buffer_free(idp2);
}
for the killing. */
void silc_server_send_notify_killed(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcClientID *client_id,
const char *comment,
void *killer, SilcIdType killer_type)
idp2 = silc_id_payload_encode(killer, killer_type);
silc_server_send_notify_dest(server, sock, broadcast, (void *)client_id,
SILC_ID_CLIENT, SILC_NOTIFY_TYPE_KILLED,
- 3, idp1->data, idp1->len,
+ 3, idp1->data, silc_buffer_len(idp1),
comment, comment ? strlen(comment) : 0,
- idp2->data, idp2->len);
+ idp2->data, silc_buffer_len(idp2));
silc_buffer_free(idp1);
silc_buffer_free(idp2);
}
send the packet between routers as broadcast packet. */
void silc_server_send_notify_umode(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcClientID *client_id,
SilcUInt32 mode_mask)
{
silc_server_send_notify(server, sock, broadcast,
SILC_NOTIFY_TYPE_UMODE_CHANGE, 2,
- idp->data, idp->len,
+ idp->data, silc_buffer_len(idp),
mode, 4);
silc_buffer_free(idp);
}
between routers as broadcast packet. */
void silc_server_send_notify_ban(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
unsigned char *action,
SilcBuffer list)
idp = silc_id_payload_encode((void *)channel->id, SILC_ID_CHANNEL);
silc_server_send_notify(server, sock, broadcast,
SILC_NOTIFY_TYPE_BAN, 3,
- idp->data, idp->len,
+ idp->data, silc_buffer_len(idp),
action ? action : NULL, action ? 1 : 0,
- list ? list->data : NULL, list ? list->len : 0);
+ list ? list->data : NULL,
+ list ? silc_buffer_len(list) : 0);
silc_buffer_free(idp);
}
packet. */
void silc_server_send_notify_invite(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
unsigned char *action,
idp2 = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
silc_server_send_notify(server, sock, broadcast,
SILC_NOTIFY_TYPE_INVITE, 5,
- idp->data, idp->len,
+ idp->data, silc_buffer_len(idp),
channel->channel_name, strlen(channel->channel_name),
- idp2->data, idp2->len,
+ idp2->data, silc_buffer_len(idp2),
action ? action : NULL, action ? 1 : 0,
- list ? list->data : NULL, list ? list->len : 0);
+ list ? list->data : NULL,
+ list ? silc_buffer_len(list) : 0);
silc_buffer_free(idp);
silc_buffer_free(idp2);
}
its status in the network has changed. */
void silc_server_send_notify_watch(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcClientEntry watcher,
SilcClientEntry client,
const char *nickname,
SILC_PUT16_MSB(type, n);
SILC_PUT32_MSB(client->mode, mode);
if (public_key)
- pkp = silc_pkcs_public_key_payload_encode(public_key);
+ pkp = silc_public_key_payload_encode(public_key);
silc_server_send_notify_dest(server, sock, FALSE, watcher->id,
SILC_ID_CLIENT, SILC_NOTIFY_TYPE_WATCH,
- 5, idp->data, idp->len,
+ 5, idp->data, silc_buffer_len(idp),
nickname, nickname ? strlen(nickname) : 0,
mode, sizeof(mode),
type != SILC_NOTIFY_TYPE_NONE ?
n : NULL, sizeof(n),
pkp ? pkp->data : NULL,
- pkp ? pkp->len : 0);
+ pkp ? silc_buffer_len(pkp) : 0);
silc_buffer_free(idp);
silc_buffer_free(pkp);
}
/* Sends notify message destined to specific entity. */
void silc_server_send_notify_dest(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
void *dest_id,
SilcIdType dest_id_type,
SilcNotifyType type,
silc_server_packet_send_dest(server, sock, SILC_PACKET_NOTIFY,
broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
dest_id, dest_id_type,
- packet->data, packet->len, FALSE);
+ packet->data, silc_buffer_len(packet));
/* Send to backup routers if this is being broadcasted to primary
router. The silc_server_backup_send checks further whether to
(broadcast && !sock && !SILC_PRIMARY_ROUTE(server)))
silc_server_backup_send_dest(server, NULL, SILC_PACKET_NOTIFY, 0,
dest_id, dest_id_type,
- packet->data, packet->len, FALSE, TRUE);
+ packet->data, silc_buffer_len(packet),
+ FALSE, TRUE);
silc_buffer_free(packet);
va_end(ap);
originally came from it. */
void silc_server_send_notify_to_channel(SilcServer server,
- SilcSocketConnection sender,
+ SilcPacketStream sender,
SilcChannelEntry channel,
- bool route_notify,
- bool send_to_clients,
+ SilcBool route_notify,
+ SilcBool send_to_clients,
SilcNotifyType type,
SilcUInt32 argc, ...)
{
silc_server_packet_send_to_channel(server, sender, channel,
SILC_PACKET_NOTIFY, route_notify,
send_to_clients,
- packet->data, packet->len, FALSE);
+ packet->data, silc_buffer_len(packet));
silc_buffer_free(packet);
va_end(ap);
}
SilcUInt32 argc, ...)
{
int k;
- SilcSocketConnection sock = NULL;
- SilcPacketContext packetdata;
+ SilcPacketStream sock = NULL;
SilcClientEntry c;
SilcClientEntry *sent_clients = NULL;
SilcUInt32 sent_clients_count = 0;
SilcHashTableList htl, htl2;
SilcChannelEntry channel;
SilcChannelClientEntry chl, chl2;
- SilcIDListData idata;
SilcBuffer packet;
unsigned char *data;
SilcUInt32 data_len;
- bool force_send = FALSE;
va_list ap;
if (!silc_hash_table_count(client->channels)) {
va_start(ap, argc);
packet = silc_notify_payload_encode(type, argc, ap);
data = packet->data;
- data_len = packet->len;
-
- /* Set the packet context pointers. */
- packetdata.flags = 0;
- packetdata.type = SILC_PACKET_NOTIFY;
- packetdata.src_id = silc_id_id2str(server->id, SILC_ID_SERVER);
- packetdata.src_id_len = silc_id_get_len(server->id, SILC_ID_SERVER);
- packetdata.src_id_type = SILC_ID_SERVER;
+ data_len = silc_buffer_len(packet);
silc_hash_table_list(client->channels, &htl);
while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
if (k < routed_count)
continue;
- /* Get data used in packet header encryption, keys and stuff. */
- sock = (SilcSocketConnection)c->router->connection;
- idata = (SilcIDListData)c->router;
-
- {
- SILC_LOG_DEBUG(("*****************"));
- SILC_LOG_DEBUG(("client->router->id %s",
- silc_id_render(c->router->id, SILC_ID_SERVER)));
- SILC_LOG_DEBUG(("client->router->connection->user_data->id %s",
- silc_id_render(((SilcServerEntry)sock->user_data)->id, SILC_ID_SERVER)));
- }
-
- packetdata.dst_id = silc_id_id2str(c->router->id, SILC_ID_SERVER);
- packetdata.dst_id_len = silc_id_get_len(c->router->id, SILC_ID_SERVER);
- packetdata.dst_id_type = SILC_ID_SERVER;
+ sock = c->router->connection;
/* Send the packet */
- silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key,
- idata->hmac_send,
- idata->psn_send++,
- data, data_len, FALSE,
- force_send);
-
- silc_free(packetdata.dst_id);
+ silc_server_packet_send_dest(server, sock, SILC_PACKET_NOTIFY, 0,
+ c->router->id, SILC_ID_SERVER,
+ data, data_len);
/* We want to make sure that the packet is routed to same router
only once. Mark this route as sent route. */
/* Send to locally connected client */
if (c) {
-
- /* Get data used in packet header encryption, keys and stuff. */
- sock = (SilcSocketConnection)c->connection;
- idata = (SilcIDListData)c;
-
+ sock = c->connection;
if (!sock)
continue;
- packetdata.dst_id = silc_id_id2str(c->id, SILC_ID_CLIENT);
- packetdata.dst_id_len = silc_id_get_len(c->id, SILC_ID_CLIENT);
- packetdata.dst_id_type = SILC_ID_CLIENT;
-
/* Send the packet */
- silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key,
- idata->hmac_send,
- idata->psn_send++,
- data, data_len, FALSE,
- force_send);
-
- silc_free(packetdata.dst_id);
+ silc_server_packet_send_dest(server, sock, SILC_PACKET_NOTIFY, 0,
+ c->id, SILC_ID_CLIENT, data, data_len);
/* Make sure that we send the notify only once per client. */
sent_clients = silc_realloc(sent_clients, sizeof(*sent_clients) *
silc_hash_table_list_reset(&htl);
silc_free(routed);
silc_free(sent_clients);
- silc_free(packetdata.src_id);
silc_buffer_free(packet);
va_end(ap);
}
broadcast packet. */
void silc_server_send_new_id(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
void *id, SilcIdType id_type,
SilcUInt32 id_len)
{
idp = silc_id_payload_encode(id, id_type);
silc_server_packet_send(server, sock, SILC_PACKET_NEW_ID,
broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
- idp->data, idp->len, FALSE);
+ idp->data, silc_buffer_len(idp));
silc_buffer_free(idp);
}
about new channel. This packet is broadcasted by router. */
void silc_server_send_new_channel(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
char *channel_name,
void *channel_id,
SilcUInt32 channel_id_len,
SilcUInt32 mode)
{
SilcBuffer packet;
- unsigned char *cid;
+ unsigned char cid[32];
SilcUInt32 name_len = strlen(channel_name);
SILC_LOG_DEBUG(("Sending new channel"));
- cid = silc_id_id2str(channel_id, SILC_ID_CHANNEL);
- if (!cid)
+ if (!silc_id_id2str(channel_id, SILC_ID_CHANNEL, cid, sizeof(cid),
+ &channel_id_len))
return;
/* Encode the channel payload */
silc_server_packet_send(server, sock, SILC_PACKET_NEW_CHANNEL,
broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
- packet->data, packet->len, FALSE);
+ packet->data, silc_buffer_len(packet));
- silc_free(cid);
silc_buffer_free(packet);
}
it originally came from it. */
void silc_server_send_channel_key(SilcServer server,
- SilcSocketConnection sender,
+ SilcPacketStream sender,
SilcChannelEntry channel,
unsigned char route)
{
SilcBuffer packet;
- unsigned char *chid;
- SilcUInt32 tmp_len;
+ unsigned char cid[32];
+ SilcUInt32 tmp_len, cid_len;
const char *cipher;
SILC_LOG_DEBUG(("Sending key to channel %s", channel->channel_name));
- chid = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- if (!chid)
+ if (!channel->key)
return;
- if (!channel->channel_key)
+ if (!silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid),
+ &cid_len))
return;
/* Encode channel key packet */
- cipher = silc_cipher_get_name(channel->channel_key);
+ cipher = silc_cipher_get_name(channel->send_key);
tmp_len = strlen(cipher);
- packet = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
- SILC_ID_CHANNEL),
- chid, tmp_len, cipher,
+ packet = silc_channel_key_payload_encode(cid_len, cid, tmp_len, cipher,
channel->key_len / 8, channel->key);
silc_server_packet_send_to_channel(server, sender, channel,
SILC_PACKET_CHANNEL_KEY,
- route, TRUE, packet->data, packet->len,
- FALSE);
+ route, TRUE, packet->data,
+ silc_buffer_len(packet));
silc_buffer_free(packet);
- silc_free(chid);
}
/* Generic function to send any command. The arguments must be sent already
encoded into correct form in correct order. */
void silc_server_send_command(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcCommand command,
SilcUInt16 ident,
SilcUInt32 argc, ...)
packet = silc_command_payload_encode_vap(command, ident, argc, ap);
silc_server_packet_send(server, sock, SILC_PACKET_COMMAND, 0,
- packet->data, packet->len, FALSE);
+ packet->data, silc_buffer_len(packet));
silc_buffer_free(packet);
va_end(ap);
}
already encoded into correct form in correct order. */
void silc_server_send_command_reply(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcCommand command,
SilcStatus status,
SilcStatus error,
packet = silc_command_reply_payload_encode_vap(command, status, error,
ident, argc, ap);
silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
- packet->data, packet->len, FALSE);
+ packet->data, silc_buffer_len(packet));
silc_buffer_free(packet);
va_end(ap);
}
already encoded into correct form in correct order. */
void silc_server_send_dest_command_reply(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
void *dst_id,
SilcIdType dst_id_type,
SilcCommand command,
ident, argc, ap);
silc_server_packet_send_dest(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
dst_id, dst_id_type, packet->data,
- packet->len, FALSE);
+ silc_buffer_len(packet));
silc_buffer_free(packet);
va_end(ap);
}
-/* Send the heartbeat packet. */
-
-void silc_server_send_heartbeat(SilcServer server,
- SilcSocketConnection sock)
-{
- silc_server_packet_send(server, sock, SILC_PACKET_HEARTBEAT, 0,
- NULL, 0, FALSE);
-}
-
-/* Generic function to relay packet we've received. This is used to relay
- packets to a client but generally can be used to other purposes as well. */
-
-void silc_server_relay_packet(SilcServer server,
- SilcSocketConnection dst_sock,
- SilcCipher cipher,
- SilcHmac hmac,
- SilcUInt32 sequence,
- SilcPacketContext *packet,
- bool force_send)
-{
- const SilcBufferStruct p;
-
- silc_buffer_push(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len
- + packet->dst_id_len + packet->padlen);
- if (!silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len, hmac,
- (const SilcBuffer)&p)) {
- SILC_LOG_ERROR(("Cannot send packet"));
- return;
- }
- silc_buffer_put((SilcBuffer)&p, packet->buffer->data, packet->buffer->len);
-
- /* Re-encrypt packet */
- silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p, p.len);
-
- /* Send the packet */
- silc_server_packet_send_real(server, dst_sock, force_send);
-
- silc_buffer_pull(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len
- + packet->dst_id_len + packet->padlen);
-
- /* Check for mandatory rekey */
- if (sequence == SILC_SERVER_REKEY_THRESHOLD)
- silc_schedule_task_add(server->schedule, dst_sock->sock,
- silc_server_rekey_callback, dst_sock, 0, 1,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-}
-
/* Routine used to send the connection authentication packet. */
void silc_server_send_connection_auth_request(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcUInt16 conn_type,
SilcAuthMethod auth_meth)
{
SilcBuffer packet;
packet = silc_buffer_alloc(4);
- silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
+ silc_buffer_pull_tail(packet, silc_buffer_truelen(packet));
silc_buffer_format(packet,
SILC_STR_UI_SHORT(conn_type),
SILC_STR_UI_SHORT(auth_meth),
SILC_STR_END);
silc_server_packet_send(server, sock, SILC_PACKET_CONNECTION_AUTH_REQUEST,
- 0, packet->data, packet->len, FALSE);
+ 0, packet->data, silc_buffer_len(packet));
silc_buffer_free(packet);
}
-/* Purge the outgoing packet queue to the network if there is data. This
- function can be used to empty the packet queue. */
-
-void silc_server_packet_queue_purge(SilcServer server,
- SilcSocketConnection sock)
-{
- if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
- !(SILC_IS_DISCONNECTING(sock)) && !(SILC_IS_DISCONNECTED(sock))) {
- int ret;
-
- SILC_LOG_DEBUG(("Purging outgoing queue"));
-
- server->stat.packets_sent++;
- ret = silc_packet_send(sock, TRUE);
- if (ret == -2) {
- if (sock->outbuf && sock->outbuf->len > 0) {
- /* Couldn't send all data, put the queue back up, we'll send
- rest later. */
- SILC_LOG_DEBUG(("Could not purge immediately, sending rest later"));
- SILC_SET_CONNECTION_FOR_OUTPUT(server->schedule, sock->sock);
- SILC_SET_OUTBUF_PENDING(sock);
- return;
- }
- } else if (ret == -1) {
- SILC_LOG_ERROR(("Error purging packet queue, packets dropped"));
- }
-
- /* Purged all data */
- SILC_SET_CONNECTION_FOR_INPUT(server->schedule, sock->sock);
- SILC_UNSET_OUTBUF_PENDING(sock);
- silc_buffer_clear(sock->outbuf);
- }
-}
-
/* Send packet to clients that are known to be operators. If server
is router and `route' is TRUE then the packet would go to all operators
in the SILC network. If `route' is FALSE then only local operators
void silc_server_send_opers(SilcServer server,
SilcPacketType type,
SilcPacketFlags flags,
- bool route, bool local,
+ SilcBool route, bool local,
unsigned char *data,
- SilcUInt32 data_len,
- bool force_send)
+ SilcUInt32 data_len)
{
- SilcIDCacheList list = NULL;
+ SilcList list;
SilcIDCacheEntry id_cache = NULL;
SilcClientEntry client = NULL;
- SilcSocketConnection sock;
+ SilcIDListData idata;
+ SilcPacketStream sock;
SilcServerEntry *routed = NULL;
SilcUInt32 routed_count = 0;
- bool gone = FALSE;
+ SilcBool gone = FALSE;
int k;
SILC_LOG_DEBUG(("Sending %s packet to operators",
/* If local was requested send only locally connected operators. */
if (local || (server->server_type == SILC_SERVER && !route)) {
- if (!silc_idcache_get_all(server->local_list->clients, &list) ||
- !silc_idcache_list_first(list, &id_cache))
+ if (!silc_idcache_get_all(server->local_list->clients, &list))
return;
- while (id_cache) {
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
client = (SilcClientEntry)id_cache->context;
if (!client->router && SILC_IS_LOCAL(client) &&
(client->mode & SILC_UMODE_SERVER_OPERATOR ||
/* Send the packet to locally connected operator */
silc_server_packet_send_dest(server, client->connection, type, flags,
client->id, SILC_ID_CLIENT,
- data, data_len, force_send);
+ data, data_len);
}
-
- if (!silc_idcache_list_next(list, &id_cache))
- break;
}
- silc_idcache_list_free(list);
return;
}
- if (!silc_idcache_get_all(server->local_list->clients, &list) ||
- !silc_idcache_list_first(list, &id_cache))
+ if (!silc_idcache_get_all(server->local_list->clients, &list))
return;
- while (id_cache) {
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
client = (SilcClientEntry)id_cache->context;
if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
- goto next;
+ continue;
if (server->server_type != SILC_SERVER && client->router &&
((!route && client->router->router == server->id_entry) || route)) {
if (routed[k] == client->router)
break;
if (k < routed_count)
- goto next;
+ continue;
/* Route only once to router */
- sock = (SilcSocketConnection)client->router->connection;
- if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ sock = client->router->connection;
+ idata = silc_packet_get_context(sock);
+ if (idata->conn_type == SILC_CONN_ROUTER) {
if (gone)
- goto next;
+ continue;
gone = TRUE;
}
/* Send the packet */
silc_server_packet_send_dest(server, sock, type, flags,
client->id, SILC_ID_CLIENT,
- data, data_len, force_send);
+ data, data_len);
/* Mark this route routed already */
routed = silc_realloc(routed, sizeof(*routed) * (routed_count + 1));
routed[routed_count++] = client->router;
- goto next;
+ continue;
}
if (client->router || !client->connection)
- goto next;
+ continue;
/* Send to locally connected client */
- sock = (SilcSocketConnection)client->connection;
+ sock = client->connection;
silc_server_packet_send_dest(server, sock, type, flags,
client->id, SILC_ID_CLIENT,
- data, data_len, force_send);
+ data, data_len);
- next:
- if (!silc_idcache_list_next(list, &id_cache))
- break;
}
- silc_idcache_list_free(list);
- if (!silc_idcache_get_all(server->global_list->clients, &list) ||
- !silc_idcache_list_first(list, &id_cache))
+ if (!silc_idcache_get_all(server->global_list->clients, &list))
return;
- while (id_cache) {
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
client = (SilcClientEntry)id_cache->context;
if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
- goto nextg;
+ continue;
if (server->server_type != SILC_SERVER && client->router &&
((!route && client->router->router == server->id_entry) || route)) {
if (routed[k] == client->router)
break;
if (k < routed_count)
- goto nextg;
+ continue;
/* Route only once to router */
- sock = (SilcSocketConnection)client->router->connection;
- if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ sock = client->router->connection;
+ idata = silc_packet_get_context(sock);
+ if (idata->conn_type == SILC_CONN_ROUTER) {
if (gone)
- goto nextg;
+ continue;
gone = TRUE;
}
/* Send the packet */
silc_server_packet_send_dest(server, sock, type, flags,
client->id, SILC_ID_CLIENT,
- data, data_len, force_send);
+ data, data_len);
/* Mark this route routed already */
routed = silc_realloc(routed, sizeof(*routed) * (routed_count + 1));
routed[routed_count++] = client->router;
- goto nextg;
+ continue;
}
if (client->router || !client->connection)
- goto nextg;
+ continue;
/* Send to locally connected client */
- sock = (SilcSocketConnection)client->connection;
+ sock = client->connection;
silc_server_packet_send_dest(server, sock, type, flags,
client->id, SILC_ID_CLIENT,
- data, data_len, force_send);
-
- nextg:
- if (!silc_idcache_list_next(list, &id_cache))
- break;
+ data, data_len);
}
- silc_idcache_list_free(list);
silc_free(routed);
}
/* Send a notify packet to operators */
void silc_server_send_opers_notify(SilcServer server,
- bool route,
- bool local,
+ SilcBool route,
+ SilcBool local,
SilcNotifyType type,
SilcUInt32 argc, ...)
{
va_start(ap, argc);
packet = silc_notify_payload_encode(type, argc, ap);
silc_server_send_opers(server, SILC_PACKET_NOTIFY, 0,
- route, local, packet->data, packet->len,
- FALSE);
+ route, local, packet->data, silc_buffer_len(packet));
silc_buffer_free(packet);
va_end(ap);
}
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2004 Pekka Riikonen
+ Copyright (C) 1997 - 2004, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Prototypes */
-int silc_server_packet_send_real(SilcServer server,
- SilcSocketConnection sock,
- bool force_send);
-void silc_server_packet_send(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketType type,
- SilcPacketFlags flags,
- unsigned char *data,
- SilcUInt32 data_len,
- bool force_send);
-void silc_server_packet_send_dest(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketType type,
- SilcPacketFlags flags,
- void *dst_id,
- SilcIdType dst_id_type,
- unsigned char *data,
- SilcUInt32 data_len,
- bool force_send);
-void silc_server_packet_send_srcdest(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketType type,
- SilcPacketFlags flags,
- void *src_id,
- SilcIdType src_id_type,
- void *dst_id,
- SilcIdType dst_id_type,
- unsigned char *data,
- SilcUInt32 data_len,
- bool force_send);
-void silc_server_packet_broadcast(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
-void silc_server_packet_route(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+SilcBool silc_server_packet_send(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacketType type,
+ SilcPacketFlags flags,
+ unsigned char *data,
+ SilcUInt32 data_len);
+SilcBool silc_server_packet_send_dest(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacketType type,
+ SilcPacketFlags flags,
+ void *dst_id,
+ SilcIdType dst_id_type,
+ unsigned char *data,
+ SilcUInt32 data_len);
+SilcBool silc_server_packet_send_srcdest(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacketType type,
+ SilcPacketFlags flags,
+ void *src_id,
+ SilcIdType src_id_type,
+ void *dst_id,
+ SilcIdType dst_id_type,
+ unsigned char *data,
+ SilcUInt32 data_len);
+SilcBool silc_server_packet_broadcast(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacket packet);
+SilcBool silc_server_packet_route(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacket packet);
void silc_server_packet_send_clients(SilcServer server,
SilcHashTable clients,
SilcPacketType type,
SilcPacketFlags flags,
- bool route,
+ SilcBool route,
unsigned char *data,
- SilcUInt32 data_len,
- bool force_send);
+ SilcUInt32 data_len);
void silc_server_packet_send_to_channel(SilcServer server,
- SilcSocketConnection sender,
+ SilcPacketStream sender,
SilcChannelEntry channel,
SilcPacketType type,
- bool route,
- bool send_to_clients,
+ SilcBool route,
+ SilcBool send_to_clients,
unsigned char *data,
- SilcUInt32 data_len,
- bool force_send);
+ SilcUInt32 data_len);
void silc_server_packet_relay_to_channel(SilcServer server,
- SilcSocketConnection sender_sock,
+ SilcPacketStream sender_sock,
SilcChannelEntry channel,
void *sender_id,
SilcIdType sender_type,
SilcClientEntry sender_entry,
unsigned char *data,
- SilcUInt32 data_len,
- bool force_send);
+ SilcUInt32 data_len);
void silc_server_packet_send_local_channel(SilcServer server,
SilcChannelEntry channel,
SilcPacketType type,
SilcPacketFlags flags,
unsigned char *data,
- SilcUInt32 data_len,
- bool force_send);
-void silc_server_send_private_message(SilcServer server,
- SilcSocketConnection dst_sock,
- SilcCipher cipher,
- SilcHmac hmac,
- SilcUInt32 sequence,
- SilcPacketContext *packet);
+ SilcUInt32 data_len);
void silc_server_send_motd(SilcServer server,
- SilcSocketConnection sock);
+ SilcPacketStream sock);
void silc_server_send_error(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
const char *fmt, ...);
void silc_server_send_notify(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcNotifyType type,
SilcUInt32 argc, ...);
void silc_server_send_notify_args(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcNotifyType type,
SilcUInt32 argc,
SilcBuffer args);
void silc_server_send_notify_channel_change(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelID *old_id,
SilcChannelID *new_id);
void silc_server_send_notify_nick_change(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcClientID *old_id,
SilcClientID *new_id,
const char *nickname);
void silc_server_send_notify_join(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id);
void silc_server_send_notify_leave(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id);
void silc_server_send_notify_cmode(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
SilcUInt32 mode_mask,
void *id, SilcIdType id_type,
SilcPublicKey founder_key,
SilcBuffer channel_pubkeys);
void silc_server_send_notify_cumode(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
SilcUInt32 mode_mask,
void *id, SilcIdType id_type,
SilcClientID *target,
SilcPublicKey founder_key);
void silc_server_send_notify_signoff(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcClientID *client_id,
const char *message);
void silc_server_send_notify_topic_set(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
void *id, SilcIdType id_type,
char *topic);
void silc_server_send_notify_kicked(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
SilcClientID *kicker,
char *comment);
void silc_server_send_notify_killed(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcClientID *client_id,
const char *comment,
void *killer, SilcIdType killer_type);
void silc_server_send_notify_umode(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcClientID *client_id,
SilcUInt32 mode_mask);
void silc_server_send_notify_ban(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
unsigned char *action,
SilcBuffer list);
void silc_server_send_notify_invite(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
unsigned char *action,
SilcBuffer list);
void silc_server_send_notify_watch(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcClientEntry watcher,
SilcClientEntry client,
const char *nickname,
SilcNotifyType type,
SilcPublicKey public_key);
void silc_server_send_notify_dest(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
void *dest_id,
SilcIdType dest_id_type,
SilcNotifyType type,
SilcUInt32 argc, ...);
void silc_server_send_notify_to_channel(SilcServer server,
- SilcSocketConnection sender,
+ SilcPacketStream sender,
SilcChannelEntry channel,
- bool route_notify,
- bool send_to_clients,
+ SilcBool route_notify,
+ SilcBool send_to_clients,
SilcNotifyType type,
SilcUInt32 argc, ...);
void silc_server_send_notify_on_channels(SilcServer server,
SilcNotifyType type,
SilcUInt32 argc, ...);
void silc_server_send_new_id(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
void *id, SilcIdType id_type,
SilcUInt32 id_len);
void silc_server_send_new_channel(SilcServer server,
- SilcSocketConnection sock,
- bool broadcast,
+ SilcPacketStream sock,
+ SilcBool broadcast,
char *channel_name,
void *channel_id,
SilcUInt32 channel_id_len,
SilcUInt32 mode);
void silc_server_send_channel_key(SilcServer server,
- SilcSocketConnection sender,
+ SilcPacketStream sender,
SilcChannelEntry channel,
unsigned char route);
void silc_server_send_command(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcCommand command,
SilcUInt16 ident,
SilcUInt32 argc, ...);
void silc_server_send_command_reply(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcCommand command,
SilcStatus status,
SilcStatus error,
SilcUInt16 ident,
SilcUInt32 argc, ...);
void silc_server_send_dest_command_reply(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
void *dst_id,
SilcIdType dst_id_type,
SilcCommand command,
SilcStatus error,
SilcUInt16 ident,
SilcUInt32 argc, ...);
-void silc_server_send_heartbeat(SilcServer server,
- SilcSocketConnection sock);
void silc_server_relay_packet(SilcServer server,
- SilcSocketConnection dst_sock,
+ SilcPacketStream dst_sock,
SilcCipher cipher,
SilcHmac hmac,
SilcUInt32 sequence,
- SilcPacketContext *packet,
- bool force_send);
+ SilcPacket *packet);
void silc_server_send_connection_auth_request(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcUInt16 conn_type,
SilcAuthMethod auth_meth);
-void silc_server_packet_queue_purge(SilcServer server,
- SilcSocketConnection sock);
void silc_server_send_opers(SilcServer server,
SilcPacketType type,
SilcPacketFlags flags,
- bool route, bool local,
+ SilcBool route, bool local,
unsigned char *data,
- SilcUInt32 data_len,
- bool force_send);
+ SilcUInt32 data_len);
void silc_server_send_opers_notify(SilcServer server,
- bool route,
- bool local,
+ SilcBool route,
+ SilcBool local,
SilcNotifyType type,
SilcUInt32 argc, ...);
+++ /dev/null
-/*
-
- protocol.c
-
- Author: Pekka Riikonen <priikone@silcnet.org>
-
- Copyright (C) 1997 - 2003 Pekka Riikonen
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
-*/
-/*
- * Server side of the protocols.
- */
-/* $Id$ */
-
-#include "serverincludes.h"
-#include "server_internal.h"
-
-SILC_TASK_CALLBACK(silc_server_protocol_connection_auth);
-SILC_TASK_CALLBACK(silc_server_protocol_key_exchange);
-SILC_TASK_CALLBACK(silc_server_protocol_rekey);
-
-/*
- * Key Exhange protocol functions
- */
-
-static bool
-silc_verify_public_key_internal(SilcServer server, SilcSocketConnection sock,
- SilcSocketType conn_type,
- unsigned char *pk, SilcUInt32 pk_len,
- SilcSKEPKType pk_type)
-{
- char file[256], filename[256], *fingerprint;
- struct stat st;
-
- if (pk_type != SILC_SKE_PK_TYPE_SILC) {
- SILC_LOG_WARNING(("We don't support %s (%s) port %d public key type %d",
- sock->hostname, sock->ip, sock->port, pk_type));
- return FALSE;
- }
-
- /* Accept client keys without verification */
- if (conn_type == SILC_SOCKET_TYPE_CLIENT) {
- SILC_LOG_DEBUG(("Accepting client public key without verification"));
- return TRUE;
- }
-
- /* XXX For now, accept server keys without verification too. We are
- currently always doing mutual authentication so the proof of posession
- of the private key is verified, and if server is authenticated in
- conn auth protocol with public key we MUST have the key already. */
- return TRUE;
- /* Rest is unreachable code! */
-
- memset(filename, 0, sizeof(filename));
- memset(file, 0, sizeof(file));
- snprintf(file, sizeof(file) - 1, "serverkey_%s_%d.pub", sock->hostname,
- sock->port);
- snprintf(filename, sizeof(filename) - 1, SILC_ETCDIR "/serverkeys/%s",
- file);
-
- /* Create serverkeys directory if it doesn't exist. */
- if (stat(SILC_ETCDIR "/serverkeys", &st) < 0) {
- /* If dir doesn't exist */
- if (errno == ENOENT) {
- if (mkdir(SILC_ETCDIR "/serverkeys", 0755) < 0) {
- SILC_LOG_ERROR(("Couldn't create `%s' directory\n",
- SILC_ETCDIR "/serverkeys"));
- return TRUE;
- }
- } else {
- SILC_LOG_ERROR(("%s\n", strerror(errno)));
- return TRUE;
- }
- }
-
- /* Take fingerprint of the public key */
- fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
- SILC_LOG_DEBUG(("Received server %s (%s) port %d public key (%s)",
- sock->hostname, sock->ip, sock->port, fingerprint));
- silc_free(fingerprint);
-
- /* Check whether this key already exists */
- if (stat(filename, &st) < 0) {
- /* We don't have it, then cache it. */
- SILC_LOG_DEBUG(("New public key from server"));
-
- silc_pkcs_save_public_key_data(filename, pk, pk_len,
- SILC_PKCS_FILE_PEM);
- return TRUE;
- } else {
- /* The key already exists, verify it. */
- SilcPublicKey public_key;
- unsigned char *encpk;
- SilcUInt32 encpk_len;
-
- SILC_LOG_DEBUG(("We have the public key saved locally"));
-
- /* Load the key file */
- if (!silc_pkcs_load_public_key(filename, &public_key,
- SILC_PKCS_FILE_PEM))
- if (!silc_pkcs_load_public_key(filename, &public_key,
- SILC_PKCS_FILE_BIN)) {
- SILC_LOG_WARNING(("Could not load local copy of the %s (%s) port %d "
- "server public key", sock->hostname, sock->ip,
- sock->port));
-
- /* Save the key for future checking */
- unlink(filename);
- silc_pkcs_save_public_key_data(filename, pk, pk_len,
- SILC_PKCS_FILE_PEM);
- return TRUE;
- }
-
- /* Encode the key data */
- encpk = silc_pkcs_public_key_encode(public_key, &encpk_len);
- if (!encpk) {
- SILC_LOG_WARNING(("Local copy of the server %s (%s) port %d public key "
- "is malformed", sock->hostname, sock->ip, sock->port));
-
- /* Save the key for future checking */
- unlink(filename);
- silc_pkcs_save_public_key_data(filename, pk, pk_len, SILC_PKCS_FILE_PEM);
- return TRUE;
- }
-
- if (memcmp(pk, encpk, encpk_len)) {
- SILC_LOG_WARNING(("%s (%s) port %d server public key does not match "
- "with local copy", sock->hostname, sock->ip,
- sock->port));
- SILC_LOG_WARNING(("It is possible that the key has expired or changed"));
- SILC_LOG_WARNING(("It is also possible that some one is performing "
- "man-in-the-middle attack"));
- SILC_LOG_WARNING(("Will not accept the server %s (%s) port %d public "
- "key",
- sock->hostname, sock->ip, sock->port));
- return FALSE;
- }
-
- /* Local copy matched */
- return TRUE;
- }
-}
-
-/* Callback that is called when we have received KE2 payload from
- responder. We try to verify the public key now. */
-
-static void
-silc_server_protocol_ke_verify_key(SilcSKE ske,
- unsigned char *pk_data,
- SilcUInt32 pk_len,
- SilcSKEPKType pk_type,
- void *context,
- SilcSKEVerifyCbCompletion completion,
- void *completion_context)
-{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerKEInternalContext *ctx =
- (SilcServerKEInternalContext *)protocol->context;
- SilcServer server = (SilcServer)ctx->server;
-
- SILC_LOG_DEBUG(("Verifying received public key"));
-
- if (silc_verify_public_key_internal(
- server, ctx->sock,
- (ctx->responder == FALSE ?
- SILC_SOCKET_TYPE_ROUTER:
- ctx->sconfig.ref_ptr ? SILC_SOCKET_TYPE_SERVER :
- ctx->rconfig.ref_ptr ? SILC_SOCKET_TYPE_ROUTER :
- SILC_SOCKET_TYPE_CLIENT),
- pk_data, pk_len, pk_type))
- completion(ske, SILC_SKE_STATUS_OK, completion_context);
- else
- completion(ske, SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
- completion_context);
-}
-
-/* Packet sending callback. This function is provided as packet sending
- routine to the Key Exchange functions. */
-
-static void silc_server_protocol_ke_send_packet(SilcSKE ske,
- SilcBuffer packet,
- SilcPacketType type,
- void *context)
-{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerKEInternalContext *ctx =
- (SilcServerKEInternalContext *)protocol->context;
- SilcServer server = (SilcServer)ctx->server;
-
- /* Send the packet immediately */
- silc_server_packet_send(server, ske->sock,
- type, 0, packet->data, packet->len, TRUE);
-}
-
-/* Sets the negotiated key material into use for particular connection. */
-
-int silc_server_protocol_ke_set_keys(SilcServer server,
- SilcSKE ske,
- SilcSocketConnection sock,
- SilcSKEKeyMaterial *keymat,
- SilcCipher cipher,
- SilcPKCS pkcs,
- SilcHash hash,
- SilcHmac hmac,
- SilcSKEDiffieHellmanGroup group,
- bool is_responder)
-{
- SilcUnknownEntry conn_data;
- SilcIDListData idata;
- const char *cname = silc_cipher_get_name(cipher);
-
- SILC_LOG_DEBUG(("Setting new keys into use"));
-
- conn_data = silc_calloc(1, sizeof(*conn_data));
- idata = (SilcIDListData)conn_data;
-
- /* Allocate cipher to be used in the communication */
- if (!silc_cipher_alloc((char *)cname, &idata->send_key)) {
- silc_free(conn_data);
- SILC_LOG_ERROR(("Cannot allocate algorithm: %s", cname));
- return FALSE;
- }
- if (!silc_cipher_alloc((char *)cname, &idata->receive_key)) {
- silc_free(conn_data);
- SILC_LOG_ERROR(("Cannot allocate algorithm: %s", cname));
- return FALSE;
- }
-
- if (!silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL,
- &idata->hmac_send)) {
- silc_cipher_free(idata->send_key);
- silc_cipher_free(idata->receive_key);
- silc_free(conn_data);
- SILC_LOG_ERROR(("Cannot allocate algorithm: %s",
- silc_hmac_get_name(hmac)));
- return FALSE;
- }
-
- if (!silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL,
- &idata->hmac_receive)) {
- silc_cipher_free(idata->send_key);
- silc_cipher_free(idata->receive_key);
- silc_hmac_free(idata->hmac_send);
- silc_free(conn_data);
- SILC_LOG_ERROR(("Cannot allocate algorithm: %s",
- silc_hmac_get_name(hmac)));
- return FALSE;
- }
-
- if (is_responder == TRUE) {
- silc_cipher_set_key(idata->send_key, keymat->receive_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(idata->send_key, keymat->receive_iv);
- silc_cipher_set_key(idata->receive_key, keymat->send_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(idata->receive_key, keymat->send_iv);
- silc_hmac_set_key(idata->hmac_send, keymat->receive_hmac_key,
- keymat->hmac_key_len);
- silc_hmac_set_key(idata->hmac_receive, keymat->send_hmac_key,
- keymat->hmac_key_len);
- } else {
- silc_cipher_set_key(idata->send_key, keymat->send_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(idata->send_key, keymat->send_iv);
- silc_cipher_set_key(idata->receive_key, keymat->receive_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(idata->receive_key, keymat->receive_iv);
- silc_hmac_set_key(idata->hmac_send, keymat->send_hmac_key,
- keymat->hmac_key_len);
- silc_hmac_set_key(idata->hmac_receive, keymat->receive_hmac_key,
- keymat->hmac_key_len);
- }
-
- idata->rekey = silc_calloc(1, sizeof(*idata->rekey));
- idata->rekey->send_enc_key = silc_memdup(keymat->send_enc_key,
- keymat->enc_key_len / 8);
- idata->rekey->enc_key_len = keymat->enc_key_len / 8;
-
- if (ske->prop->flags & SILC_SKE_SP_FLAG_PFS)
- idata->rekey->pfs = TRUE;
- idata->rekey->ske_group = silc_ske_group_get_number(group);
-
- /* Save the hash */
- if (!silc_hash_alloc(silc_hash_get_name(hash), &idata->hash)) {
- silc_cipher_free(idata->send_key);
- silc_cipher_free(idata->receive_key);
- silc_hmac_free(idata->hmac_send);
- silc_hmac_free(idata->hmac_receive);
- silc_free(conn_data);
- SILC_LOG_ERROR(("Cannot allocate algorithm: %s",
- silc_hash_get_name(hash)));
- return FALSE;
- }
-
- /* Save the remote host's public key */
- silc_pkcs_public_key_decode(ske->ke1_payload->pk_data,
- ske->ke1_payload->pk_len, &idata->public_key);
- if (ske->prop->flags & SILC_SKE_SP_FLAG_MUTUAL)
- silc_hash_make(server->sha1hash, ske->ke1_payload->pk_data,
- ske->ke1_payload->pk_len, idata->fingerprint);
-
- sock->user_data = (void *)conn_data;
-
- SILC_LOG_INFO(("%s (%s) security properties: %s %s %s %s",
- sock->hostname, sock->ip,
- silc_cipher_get_name(idata->send_key),
- (char *)silc_hmac_get_name(idata->hmac_send),
- silc_hash_get_name(idata->hash),
- ske->prop->flags & SILC_SKE_SP_FLAG_PFS ? "PFS" : ""));
-
- return TRUE;
-}
-
-/* Check remote host version string */
-
-SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
- SilcUInt32 len, void *context)
-{
- SilcUInt32 l_protocol_version = 0, r_protocol_version = 0;
-
- SILC_LOG_INFO(("%s (%s) is version %s", ske->sock->hostname,
- ske->sock->ip, version));
-
- if (!silc_parse_version_string(version, &r_protocol_version, NULL, NULL,
- NULL, NULL)) {
- SILC_LOG_ERROR(("%s (%s) %s is not allowed/supported version",
- ske->sock->hostname, ske->sock->ip, version));
- return SILC_SKE_STATUS_BAD_VERSION;
- }
-
- if (!silc_parse_version_string(silc_version_string,
- &l_protocol_version, NULL, NULL,
- NULL, NULL)) {
- SILC_LOG_ERROR(("%s (%s) %s is not allowed/supported version",
- ske->sock->hostname, ske->sock->ip, version));
- return SILC_SKE_STATUS_BAD_VERSION;
- }
-
- /* If remote is too new, don't connect */
- if (l_protocol_version < r_protocol_version) {
- SILC_LOG_ERROR(("%s (%s) %s is not allowed/supported version",
- ske->sock->hostname, ske->sock->ip, version));
- return SILC_SKE_STATUS_BAD_VERSION;
- }
-
- ske->sock->version = r_protocol_version;
-
- return SILC_SKE_STATUS_OK;
-}
-
-/* Callback that is called by the SKE to indicate that it is safe to
- continue the execution of the protocol. This is used only if we are
- initiator. Is given as argument to the silc_ske_initiator_finish or
- silc_ske_responder_phase_2 functions. This is called due to the fact
- that the public key verification process is asynchronous and we must
- not continue the protocl until the public key has been verified and
- this callback is called. */
-
-static void silc_server_protocol_ke_continue(SilcSKE ske, void *context)
-{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerKEInternalContext *ctx =
- (SilcServerKEInternalContext *)protocol->context;
- SilcServer server = (SilcServer)ctx->server;
-
- if (ske->status != SILC_SKE_STATUS_OK) {
- SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
- silc_ske_map_status(ske->status), ctx->sock->hostname,
- ctx->sock->ip));
-
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- /* Send Ok to the other end. We will end the protocol as responder
- sends Ok to us when we will take the new keys into use. */
- if (ctx->responder == FALSE) {
- SILC_LOG_DEBUG(("Ending key exchange protocol"));
- silc_ske_end(ctx->ske);
-
- /* End the protocol on the next round */
- protocol->state = SILC_PROTOCOL_STATE_END;
- }
-
- /* Advance protocol state and call the next state if we are responder.
- This happens when this callback was sent to silc_ske_responder_phase_2
- function. */
- if (ctx->responder == TRUE) {
- protocol->state++;
- silc_protocol_execute(protocol, server->schedule, 0, 100000);
- }
-}
-
-/* Performs key exchange protocol. This is used for both initiator
- and responder key exchange. This is performed always when accepting
- new connection to the server. This may be called recursively. */
-
-SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
-{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerKEInternalContext *ctx =
- (SilcServerKEInternalContext *)protocol->context;
- SilcServer server = (SilcServer)ctx->server;
- SilcSKEStatus status = SILC_SKE_STATUS_OK;
-
- if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
- protocol->state = SILC_PROTOCOL_STATE_START;
-
- SILC_LOG_DEBUG(("Current protocol state %d", protocol->state));
-
- switch(protocol->state) {
- case SILC_PROTOCOL_STATE_START:
- {
- /*
- * Start protocol
- */
- SilcSKE ske;
-
- /* Allocate Key Exchange object */
- ctx->ske = ske = silc_ske_alloc(server->rng, server);
-
- silc_ske_set_callbacks(ske, silc_server_protocol_ke_send_packet, NULL,
- silc_server_protocol_ke_verify_key,
- silc_server_protocol_ke_continue,
- silc_ske_check_version, context);
-
- if (ctx->responder == TRUE) {
- if (!ctx->packet) {
- SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
- silc_ske_map_status(status), ctx->sock->hostname,
- ctx->sock->ip));
-
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- /* Start the key exchange by processing the received security
- properties packet from initiator. */
- SILC_LOG_DEBUG(("Process security property list (KE)"));
- status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
- silc_version_string,
- ctx->packet->buffer, ctx->flags);
- } else {
- SilcSKEStartPayload *start_payload;
-
- SILC_LOG_DEBUG(("Send security property list (KE)"));
-
- /* Assemble security properties. */
- silc_ske_assemble_security_properties(ske, ctx->flags,
- silc_version_string,
- &start_payload);
-
- /* Start the key exchange by sending our security properties
- to the remote end. */
- status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
- start_payload);
- }
-
- /* Return now if the procedure is pending. */
- if (status == SILC_SKE_STATUS_PENDING)
- return;
-
- if (status != SILC_SKE_STATUS_OK) {
- SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
- silc_ske_map_status(status), ctx->sock->hostname,
- ctx->sock->ip));
-
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- /* Advance protocol state and call the next state if we are responder */
- protocol->state++;
- if (ctx->responder == TRUE)
- silc_protocol_execute(protocol, server->schedule, 0, 100000);
- }
- break;
- case 2:
- {
- /*
- * Phase 1
- */
- if (ctx->responder == TRUE) {
- /* Sends the selected security properties to the initiator. */
- SILC_LOG_DEBUG(("Send security property list reply (KE)"));
- status = silc_ske_responder_phase_1(ctx->ske);
- } else {
- if (!ctx->packet) {
- SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
- silc_ske_map_status(status), ctx->sock->hostname,
- ctx->sock->ip));
-
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- /* Call Phase-1 function. This processes the Key Exchange Start
- paylaod reply we just got from the responder. The callback
- function will receive the processed payload where we will
- save it. */
- SILC_LOG_DEBUG(("Process security property list reply (KE)"));
- status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer);
- }
-
- /* Return now if the procedure is pending. */
- if (status == SILC_SKE_STATUS_PENDING)
- return;
-
- if (status != SILC_SKE_STATUS_OK) {
- SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
- silc_ske_map_status(status), ctx->sock->hostname,
- ctx->sock->ip));
-
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- /* Advance protocol state and call next state if we are initiator */
- protocol->state++;
- if (ctx->responder == FALSE)
- silc_protocol_execute(protocol, server->schedule, 0, 100000);
- }
- break;
- case 3:
- {
- /*
- * Phase 2
- */
- if (ctx->responder == TRUE) {
- if (!ctx->packet) {
- SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
- silc_ske_map_status(status), ctx->sock->hostname,
- ctx->sock->ip));
-
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- /* Process the received Key Exchange 1 Payload packet from
- the initiator. This also creates our parts of the Diffie
- Hellman algorithm. The silc_server_protocol_ke_continue
- will be called after the public key has been verified. */
- SILC_LOG_DEBUG(("Process KE1 packet"));
- status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer);
- } else {
- /* Call the Phase-2 function. This creates Diffie Hellman
- key exchange parameters and sends our public part inside
- Key Exhange 1 Payload to the responder. */
- SILC_LOG_DEBUG(("Send KE1 packet"));
- status = silc_ske_initiator_phase_2(ctx->ske,
- server->public_key,
- server->private_key,
- SILC_SKE_PK_TYPE_SILC);
- protocol->state++;
- }
-
- /* Return now if the procedure is pending. */
- if (status == SILC_SKE_STATUS_PENDING)
- return;
-
- if (status != SILC_SKE_STATUS_OK) {
- SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
- silc_ske_map_status(status), ctx->sock->hostname,
- ctx->sock->ip));
-
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
- }
- break;
- case 4:
- {
- /*
- * Finish protocol
- */
- if (ctx->responder == TRUE) {
- /* This creates the key exchange material and sends our
- public parts to the initiator inside Key Exchange 2 Payload. */
- SILC_LOG_DEBUG(("Process KE2 packet"));
- status = silc_ske_responder_finish(ctx->ske,
- server->public_key,
- server->private_key,
- SILC_SKE_PK_TYPE_SILC);
-
- /* End the protocol on the next round */
- protocol->state = SILC_PROTOCOL_STATE_END;
- } else {
- if (!ctx->packet) {
- SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
- silc_ske_map_status(status), ctx->sock->hostname,
- ctx->sock->ip));
-
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- /* Finish the protocol. This verifies the Key Exchange 2 payload
- sent by responder. The silc_server_protocol_ke_continue will
- be called after the public key has been verified. */
- SILC_LOG_DEBUG(("Send KE2 packet"));
- status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer);
- }
-
- /* Return now if the procedure is pending. */
- if (status == SILC_SKE_STATUS_PENDING)
- return;
-
- if (status != SILC_SKE_STATUS_OK) {
- SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
- silc_ske_map_status(status), ctx->sock->hostname,
- ctx->sock->ip));
-
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
- }
- break;
-
- case SILC_PROTOCOL_STATE_END:
- {
- /*
- * End protocol
- */
- SilcSKEKeyMaterial *keymat;
- int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher);
- int hash_len = silc_hash_len(ctx->ske->prop->hash);
-
- SILC_LOG_DEBUG(("Process computed key material"));
-
- /* Process the key material */
- keymat = silc_calloc(1, sizeof(*keymat));
- status = silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len,
- keymat);
- if (status != SILC_SKE_STATUS_OK) {
- SILC_LOG_ERROR(("Error during Key Exchange protocol: "
- "could not process key material"));
-
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- silc_ske_free_key_material(keymat);
- return;
- }
- ctx->keymat = keymat;
-
- /* Send Ok to the other end if we are responder. If we are initiator
- we have sent this already. */
- if (ctx->responder == TRUE) {
- SILC_LOG_DEBUG(("Ending key exchange protocol"));
- silc_ske_end(ctx->ske);
- }
-
- /* Unregister the timeout task since the protocol has ended.
- This was the timeout task to be executed if the protocol is
- not completed fast enough. */
- if (ctx->timeout_task)
- silc_schedule_task_del(server->schedule, ctx->timeout_task);
-
- /* Assure that after calling final callback there cannot be pending
- executions for this protocol anymore. This just unregisters any
- timeout callbacks for this protocol. */
- silc_protocol_cancel(protocol, server->schedule);
-
- /* Call the final callback */
- if (protocol->final_callback)
- silc_protocol_execute_final(protocol, server->schedule);
- else
- silc_protocol_free(protocol);
- }
- break;
-
- case SILC_PROTOCOL_STATE_ERROR:
- /*
- * Error occured
- */
-
- /* Send abort notification */
- silc_ske_abort(ctx->ske, ctx->ske->status);
-
- /* Unregister the timeout task since the protocol has ended.
- This was the timeout task to be executed if the protocol is
- not completed fast enough. */
- if (ctx->timeout_task)
- silc_schedule_task_del(server->schedule, ctx->timeout_task);
-
- /* Assure that after calling final callback there cannot be pending
- executions for this protocol anymore. This just unregisters any
- timeout callbacks for this protocol. */
- silc_protocol_cancel(protocol, server->schedule);
-
- /* On error the final callback is always called. */
- if (protocol->final_callback)
- silc_protocol_execute_final(protocol, server->schedule);
- else
- silc_protocol_free(protocol);
- break;
-
- case SILC_PROTOCOL_STATE_FAILURE:
- /*
- * We have received failure from remote
- */
-
- /* Unregister the timeout task since the protocol has ended.
- This was the timeout task to be executed if the protocol is
- not completed fast enough. */
- if (ctx->timeout_task)
- silc_schedule_task_del(server->schedule, ctx->timeout_task);
-
- /* Assure that after calling final callback there cannot be pending
- executions for this protocol anymore. This just unregisters any
- timeout callbacks for this protocol. */
- silc_protocol_cancel(protocol, server->schedule);
-
- /* On error the final callback is always called. */
- if (protocol->final_callback)
- silc_protocol_execute_final(protocol, server->schedule);
- else
- silc_protocol_free(protocol);
- break;
-
- case SILC_PROTOCOL_STATE_UNKNOWN:
- break;
- }
-}
-
-/*
- * Connection Authentication protocol functions
- */
-
-static int
-silc_server_password_authentication(SilcServer server, char *local_auth,
- char *remote_auth)
-{
- if (!remote_auth || !local_auth || strlen(local_auth) != strlen(remote_auth))
- return FALSE;
-
- if (!memcmp(remote_auth, local_auth, strlen(local_auth)))
- return TRUE;
-
- return FALSE;
-}
-
-static int
-silc_server_public_key_authentication(SilcServer server,
- SilcPublicKey pub_key,
- unsigned char *sign,
- SilcUInt32 sign_len,
- SilcSKE ske)
-{
- SilcPKCS pkcs;
- int len;
- SilcBuffer auth;
-
- if (!pub_key || !sign)
- return FALSE;
-
- silc_pkcs_alloc(pub_key->name, &pkcs);
- if (!silc_pkcs_public_key_set(pkcs, pub_key)) {
- silc_pkcs_free(pkcs);
- return FALSE;
- }
-
- /* Make the authentication data. Protocol says it is HASH plus
- KE Start Payload. */
- len = ske->hash_len + ske->start_payload_copy->len;
- auth = silc_buffer_alloc(len);
- silc_buffer_pull_tail(auth, len);
- silc_buffer_format(auth,
- SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
- SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
- ske->start_payload_copy->len),
- SILC_STR_END);
-
- /* Verify signature */
- if (silc_pkcs_verify_with_hash(pkcs, ske->prop->hash, sign, sign_len,
- auth->data, auth->len)) {
- silc_pkcs_free(pkcs);
- silc_buffer_free(auth);
- return TRUE;
- }
-
- silc_pkcs_free(pkcs);
- silc_buffer_free(auth);
- return FALSE;
-}
-
-static int
-silc_server_get_public_key_auth(SilcServer server,
- unsigned char **auth_data,
- SilcUInt32 *auth_data_len,
- SilcSKE ske)
-{
- int len;
- SilcPKCS pkcs;
- SilcBuffer auth;
-
- pkcs = server->pkcs;
-
- /* Make the authentication data. Protocol says it is HASH plus
- KE Start Payload. */
- len = ske->hash_len + ske->start_payload_copy->len;
- auth = silc_buffer_alloc(len);
- silc_buffer_pull_tail(auth, len);
- silc_buffer_format(auth,
- SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
- SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
- ske->start_payload_copy->len),
- SILC_STR_END);
-
- *auth_data = silc_calloc((silc_pkcs_get_key_len(pkcs) / 8) + 1,
- sizeof(**auth_data));
- if (silc_pkcs_sign_with_hash(pkcs, ske->prop->hash, auth->data,
- auth->len, *auth_data, auth_data_len)) {
- silc_buffer_free(auth);
- return TRUE;
- }
-
- SILC_LOG_ERROR(("Error computing signature"));
-
- silc_free(*auth_data);
- silc_buffer_free(auth);
- return FALSE;
-}
-
-/* Function that actually performs the authentication to the remote. This
- supports both passphrase and public key authentication. */
-
-static bool
-silc_server_get_authentication(SilcServerConnAuthInternalContext *ctx,
- char *local_passphrase,
- SilcHashTable local_publickeys,
- unsigned char *remote_auth,
- SilcUInt32 remote_auth_len)
-{
- SilcServer server = (SilcServer)ctx->server;
- SilcSKE ske = ctx->ske;
- bool result = FALSE;
-
- /* If we don't have authentication data set at all we do not require
- authentication at all */
- if (!local_passphrase && (!local_publickeys ||
- !silc_hash_table_count(local_publickeys))) {
- SILC_LOG_DEBUG(("No authentication required"));
- return TRUE;
- }
-
- /* If both passphrase and public key is provided then we'll try both of
- them and see which one of them authenticates. If only one of them is
- set, then try only that. */
-
- /* Try first passphrase (as it is faster to check) */
- if (local_passphrase) {
- SILC_LOG_DEBUG(("Password authentication"));
- result = silc_server_password_authentication(server, local_passphrase,
- remote_auth);
- }
-
- /* Try public key authenetication */
- if (!result && local_publickeys) {
- SilcPublicKey cached_key;
- SilcPublicKey remote_key =
- ((SilcIDListData)ctx->sock->user_data)->public_key;
-
- SILC_LOG_DEBUG(("Public key authentication"));
-
- /* Find the public key to be used in authentication */
- cached_key = silc_server_find_public_key(server, local_publickeys,
- remote_key);
- if (!cached_key)
- return FALSE;
-
- result = silc_server_public_key_authentication(server, cached_key,
- remote_auth,
- remote_auth_len, ske);
- }
-
- SILC_LOG_DEBUG(("Authentication %s", result ? "successful" : "failed"));
-
- return result;
-}
-
-/* Performs connection authentication protocol. If responder, we
- authenticate the remote data received. If initiator, we will send
- authentication data to the remote end. */
-
-SILC_TASK_CALLBACK(silc_server_protocol_connection_auth)
-{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerConnAuthInternalContext *ctx =
- (SilcServerConnAuthInternalContext *)protocol->context;
- SilcServer server = (SilcServer)ctx->server;
-
- if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
- protocol->state = SILC_PROTOCOL_STATE_START;
-
- SILC_LOG_DEBUG(("Current protocol state %d", protocol->state));
-
- switch(protocol->state) {
- case SILC_PROTOCOL_STATE_START:
- {
- /*
- * Start protocol.
- */
-
- if (ctx->responder == TRUE) {
- /*
- * We are receiving party
- */
- int ret;
- SilcUInt16 payload_len;
- SilcUInt16 conn_type;
- unsigned char *auth_data = NULL;
-
- SILC_LOG_INFO(("Performing authentication protocol for %s (%s)",
- ctx->sock->hostname, ctx->sock->ip));
-
- if (!ctx->packet) {
- SILC_LOG_ERROR(("Bad authentication protocol request"));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- /* Parse the received authentication data packet. The received
- payload is Connection Auth Payload. */
- ret = silc_buffer_unformat(ctx->packet->buffer,
- SILC_STR_UI_SHORT(&payload_len),
- SILC_STR_UI_SHORT(&conn_type),
- SILC_STR_END);
- if (ret == -1) {
- SILC_LOG_ERROR(("Bad payload in authentication packet"));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- if (payload_len != ctx->packet->buffer->len) {
- SILC_LOG_ERROR(("Bad payload length in authentication packet"));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- payload_len -= 4;
-
- if (conn_type < SILC_SOCKET_TYPE_CLIENT ||
- conn_type > SILC_SOCKET_TYPE_ROUTER) {
- SILC_LOG_ERROR(("Bad connection type (%d) in authentication packet",
- conn_type));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- if (payload_len > 0) {
- /* Get authentication data */
- silc_buffer_pull(ctx->packet->buffer, 4);
- ret = silc_buffer_unformat(ctx->packet->buffer,
- SILC_STR_UI_XNSTRING_ALLOC(&auth_data,
- payload_len),
- SILC_STR_END);
- if (ret == -1) {
- SILC_LOG_DEBUG(("Bad payload in authentication payload"));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
- }
-
- /*
- * Check the remote connection type and make sure that we have
- * configured this connection. If we haven't allowed this connection
- * the authentication must be failed.
- */
-
- SILC_LOG_DEBUG(("Remote connection type %d", conn_type));
-
- /* Remote end is client */
- if (conn_type == SILC_SOCKET_TYPE_CLIENT) {
- SilcServerConfigClient *client = ctx->cconfig.ref_ptr;
-
- if (client) {
- ret = silc_server_get_authentication(ctx, client->passphrase,
- client->publickeys,
- auth_data, payload_len);
- if (!ret) {
- /* Authentication failed */
- SILC_LOG_ERROR(("Authentication failed"));
- silc_free(auth_data);
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
- } else {
- SILC_LOG_ERROR(("Remote client connection not configured"));
- SILC_LOG_ERROR(("Authentication failed"));
- silc_free(auth_data);
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule,
- 0, 300000);
- return;
- }
- }
-
- /* Remote end is server */
- if (conn_type == SILC_SOCKET_TYPE_SERVER) {
- SilcServerConfigServer *serv = ctx->sconfig.ref_ptr;
-
- if (serv) {
- ret = silc_server_get_authentication(ctx, serv->passphrase,
- serv->publickeys,
- auth_data, payload_len);
- if (!ret) {
- /* Authentication failed */
- SILC_LOG_ERROR(("Authentication failed"));
- silc_free(auth_data);
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
- } else {
- SILC_LOG_ERROR(("Remote server connection not configured"));
- SILC_LOG_ERROR(("Authentication failed"));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule,
- 0, 300000);
- silc_free(auth_data);
- return;
- }
- }
-
- /* Remote end is router */
- if (conn_type == SILC_SOCKET_TYPE_ROUTER) {
- SilcServerConfigRouter *serv = ctx->rconfig.ref_ptr;
-
- if (serv) {
- ret = silc_server_get_authentication(ctx, serv->passphrase,
- serv->publickeys,
- auth_data, payload_len);
- if (!ret) {
- /* Authentication failed */
- SILC_LOG_ERROR(("Authentication failed"));
- silc_free(auth_data);
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
- } else {
- SILC_LOG_ERROR(("Remote router connection not configured"));
- SILC_LOG_ERROR(("Authentication failed"));
- silc_free(auth_data);
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule,
- 0, 300000);
- return;
- }
- }
-
- silc_free(auth_data);
-
- /* Save connection type. This is later used to create the
- ID for the connection. */
- ctx->conn_type = conn_type;
-
- /* Advance protocol state. */
- protocol->state = SILC_PROTOCOL_STATE_END;
- silc_protocol_execute(protocol, server->schedule, 0, 0);
-
- } else {
- /*
- * We are initiator. We are authenticating ourselves to a
- * remote server. We will send the authentication data to the
- * other end for verify.
- */
- SilcBuffer packet;
- int payload_len = 0;
- unsigned char *auth_data = NULL;
- SilcUInt32 auth_data_len = 0;
-
- switch(ctx->auth_meth) {
- case SILC_AUTH_NONE:
- /* No authentication required */
- break;
-
- case SILC_AUTH_PASSWORD:
- /* Password authentication */
- if (ctx->auth_data && ctx->auth_data_len) {
- auth_data = strdup(ctx->auth_data);
- auth_data_len = ctx->auth_data_len;
- break;
- }
- break;
-
- case SILC_AUTH_PUBLIC_KEY:
- {
- /* Public key authentication */
- silc_server_get_public_key_auth(server, &auth_data, &auth_data_len,
- ctx->ske);
- break;
- }
- }
-
- payload_len = 4 + auth_data_len;
- packet = silc_buffer_alloc(payload_len);
- silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
- silc_buffer_format(packet,
- SILC_STR_UI_SHORT(payload_len),
- SILC_STR_UI_SHORT(server->server_type
- == SILC_SERVER ?
- SILC_SOCKET_TYPE_SERVER :
- SILC_SOCKET_TYPE_ROUTER),
- SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
- SILC_STR_END);
-
- /* Send the packet to server */
- silc_server_packet_send(server, ctx->sock,
- SILC_PACKET_CONNECTION_AUTH, 0,
- packet->data, packet->len, TRUE);
-
- if (auth_data) {
- memset(auth_data, 0, auth_data_len);
- silc_free(auth_data);
- }
- silc_buffer_free(packet);
-
- /* Next state is end of protocol */
- protocol->state = SILC_PROTOCOL_STATE_END;
- }
- }
- break;
-
- case SILC_PROTOCOL_STATE_END:
- {
- /*
- * End protocol
- */
- unsigned char ok[4];
-
- SILC_PUT32_MSB(SILC_AUTH_OK, ok);
-
- /* Authentication successful */
- silc_server_packet_send(server, ctx->sock, SILC_PACKET_SUCCESS,
- 0, ok, 4, TRUE);
-
- /* Unregister the timeout task since the protocol has ended.
- This was the timeout task to be executed if the protocol is
- not completed fast enough. */
- if (ctx->timeout_task)
- silc_schedule_task_del(server->schedule, ctx->timeout_task);
-
- /* Assure that after calling final callback there cannot be pending
- executions for this protocol anymore. This just unregisters any
- timeout callbacks for this protocol. */
- silc_protocol_cancel(protocol, server->schedule);
-
- /* Protocol has ended, call the final callback */
- if (protocol->final_callback)
- silc_protocol_execute_final(protocol, server->schedule);
- else
- silc_protocol_free(protocol);
- }
- break;
- case SILC_PROTOCOL_STATE_ERROR:
- {
- /*
- * Error. Send notify to remote.
- */
- unsigned char error[4];
-
- /* Authentication failed */
- SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
- silc_server_packet_send(server, ctx->sock, SILC_PACKET_FAILURE,
- 0, error, 4, TRUE);
-
- /* Unregister the timeout task since the protocol has ended.
- This was the timeout task to be executed if the protocol is
- not completed fast enough. */
- if (ctx->timeout_task)
- silc_schedule_task_del(server->schedule, ctx->timeout_task);
-
- /* Assure that after calling final callback there cannot be pending
- executions for this protocol anymore. This just unregisters any
- timeout callbacks for this protocol. */
- silc_protocol_cancel(protocol, server->schedule);
-
- /* On error the final callback is always called. */
- if (protocol->final_callback)
- silc_protocol_execute_final(protocol, server->schedule);
- else
- silc_protocol_free(protocol);
- }
- break;
-
- case SILC_PROTOCOL_STATE_FAILURE:
- /*
- * We have received failure from remote
- */
-
- SILC_LOG_ERROR(("Received Authentication Failure"));
-
- /* Unregister the timeout task since the protocol has ended.
- This was the timeout task to be executed if the protocol is
- not completed fast enough. */
- if (ctx->timeout_task)
- silc_schedule_task_del(server->schedule, ctx->timeout_task);
-
- /* Assure that after calling final callback there cannot be pending
- executions for this protocol anymore. This just unregisters any
- timeout callbacks for this protocol. */
- silc_protocol_cancel(protocol, server->schedule);
-
- /* On error the final callback is always called. */
- if (protocol->final_callback)
- silc_protocol_execute_final(protocol, server->schedule);
- else
- silc_protocol_free(protocol);
- break;
-
- case SILC_PROTOCOL_STATE_UNKNOWN:
- break;
- }
-}
-
-/*
- * Re-key protocol routines
- */
-
-/* Actually takes the new keys into use. */
-
-static void
-silc_server_protocol_rekey_validate(SilcServer server,
- SilcServerRekeyInternalContext *ctx,
- SilcIDListData idata,
- SilcSKEKeyMaterial *keymat,
- bool send)
-{
- if (ctx->responder == TRUE) {
- if (send) {
- silc_cipher_set_key(idata->send_key, keymat->receive_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(idata->send_key, keymat->receive_iv);
- silc_hmac_set_key(idata->hmac_send, keymat->receive_hmac_key,
- keymat->hmac_key_len);
- } else {
- silc_cipher_set_key(idata->receive_key, keymat->send_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(idata->receive_key, keymat->send_iv);
- silc_hmac_set_key(idata->hmac_receive, keymat->send_hmac_key,
- keymat->hmac_key_len);
- }
- } else {
- if (send) {
- silc_cipher_set_key(idata->send_key, keymat->send_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(idata->send_key, keymat->send_iv);
- silc_hmac_set_key(idata->hmac_send, keymat->send_hmac_key,
- keymat->hmac_key_len);
- } else {
- silc_cipher_set_key(idata->receive_key, keymat->receive_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(idata->receive_key, keymat->receive_iv);
- silc_hmac_set_key(idata->hmac_receive, keymat->receive_hmac_key,
- keymat->hmac_key_len);
- }
- }
-
- /* Save the current sending encryption key */
- if (!send) {
- memset(idata->rekey->send_enc_key, 0, idata->rekey->enc_key_len);
- silc_free(idata->rekey->send_enc_key);
- idata->rekey->send_enc_key = silc_memdup(keymat->send_enc_key,
- keymat->enc_key_len / 8);
- idata->rekey->enc_key_len = keymat->enc_key_len / 8;
- }
-}
-
-/* This function actually re-generates (when not using PFS) the keys and
- takes them into use. */
-
-void silc_server_protocol_rekey_generate(SilcServer server,
- SilcServerRekeyInternalContext *ctx,
- bool send)
-{
- SilcIDListData idata = (SilcIDListData)ctx->sock->user_data;
- SilcSKEKeyMaterial *keymat;
- SilcUInt32 key_len = silc_cipher_get_key_len(idata->send_key);
- SilcUInt32 hash_len = silc_hash_len(idata->hash);
-
- SILC_LOG_DEBUG(("Generating new %s session keys (no PFS)",
- send ? "sending" : "receiving"));
-
- /* Generate the new key */
- keymat = silc_calloc(1, sizeof(*keymat));
- silc_ske_process_key_material_data(idata->rekey->send_enc_key,
- idata->rekey->enc_key_len,
- 16, key_len, hash_len,
- idata->hash, keymat);
-
- /* Set the keys into use */
- silc_server_protocol_rekey_validate(server, ctx, idata, keymat, send);
-
- silc_ske_free_key_material(keymat);
-}
-
-/* This function actually re-generates (with PFS) the keys and
- takes them into use. */
-
-void
-silc_server_protocol_rekey_generate_pfs(SilcServer server,
- SilcServerRekeyInternalContext *ctx,
- bool send)
-{
- SilcIDListData idata = (SilcIDListData)ctx->sock->user_data;
- SilcSKEKeyMaterial *keymat;
- SilcUInt32 key_len = silc_cipher_get_key_len(idata->send_key);
- SilcUInt32 hash_len = silc_hash_len(idata->hash);
- unsigned char *tmpbuf;
- SilcUInt32 klen;
-
- SILC_LOG_DEBUG(("Generating new %s session keys (with PFS)",
- send ? "sending" : "receiving"));
-
- /* Encode KEY to binary data */
- tmpbuf = silc_mp_mp2bin(ctx->ske->KEY, 0, &klen);
-
- /* Generate the new key */
- keymat = silc_calloc(1, sizeof(*keymat));
- silc_ske_process_key_material_data(tmpbuf, klen, 16, key_len, hash_len,
- idata->hash, keymat);
-
- /* Set the keys into use */
- silc_server_protocol_rekey_validate(server, ctx, idata, keymat, send);
-
- memset(tmpbuf, 0, klen);
- silc_free(tmpbuf);
- silc_ske_free_key_material(keymat);
-}
-
-/* Packet sending callback. This function is provided as packet sending
- routine to the Key Exchange functions. */
-
-static void
-silc_server_protocol_rekey_send_packet(SilcSKE ske,
- SilcBuffer packet,
- SilcPacketType type,
- void *context)
-{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerRekeyInternalContext *ctx =
- (SilcServerRekeyInternalContext *)protocol->context;
- SilcServer server = (SilcServer)ctx->server;
-
- /* Send the packet immediately */
- silc_server_packet_send(server, ctx->sock,
- type, 0, packet->data, packet->len, FALSE);
-}
-
-/* Performs re-key as defined in the SILC protocol specification. */
-
-SILC_TASK_CALLBACK(silc_server_protocol_rekey)
-{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerRekeyInternalContext *ctx =
- (SilcServerRekeyInternalContext *)protocol->context;
- SilcServer server = (SilcServer)ctx->server;
- SilcIDListData idata = (SilcIDListData)ctx->sock->user_data;
- SilcSKEStatus status;
-
- if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
- protocol->state = SILC_PROTOCOL_STATE_START;
-
- SILC_LOG_DEBUG(("Current protocol state %d", protocol->state));
-
- switch(protocol->state) {
- case SILC_PROTOCOL_STATE_START:
- {
- /*
- * Start protocol.
- */
-
- if (ctx->responder == TRUE) {
- /*
- * We are receiving party
- */
-
- if (ctx->pfs == TRUE) {
- /*
- * Use Perfect Forward Secrecy, ie. negotiate the key material
- * using the SKE protocol.
- */
-
- if (!ctx->packet) {
- SILC_LOG_ERROR(("Error during Re-key, with %s (%s)",
- ctx->sock->hostname, ctx->sock->ip));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
- SILC_LOG_ERROR(("Error during Re-key (R PFS): re-key state is "
- "incorrect (received %d, expected %d packet), "
- "with %s (%s)", ctx->packet->type,
- SILC_PACKET_KEY_EXCHANGE_1, ctx->sock->hostname,
- ctx->sock->ip));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- ctx->ske = silc_ske_alloc(server->rng, server);
- ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
- silc_ske_group_get_by_number(idata->rekey->ske_group,
- &ctx->ske->prop->group);
-
- silc_ske_set_callbacks(ctx->ske,
- silc_server_protocol_rekey_send_packet,
- NULL, NULL, NULL, silc_ske_check_version,
- context);
-
- status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer);
- if (status != SILC_SKE_STATUS_OK) {
- SILC_LOG_ERROR(("Error (%s) during Re-key (R PFS), with %s (%s)",
- silc_ske_map_status(status), ctx->sock->hostname,
- ctx->sock->ip));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- /* Advance the protocol state */
- protocol->state++;
- silc_protocol_execute(protocol, server->schedule, 0, 0);
- } else {
- /*
- * Do normal and simple re-key.
- */
-
- /* Send the REKEY_DONE to indicate we will take new keys into use */
- silc_server_packet_queue_purge(server, ctx->sock);
- silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
- 0, NULL, 0, FALSE);
-
- /* After we send REKEY_DONE we must set the sending encryption
- key to the new key since all packets after this packet must
- encrypted with the new key. */
- silc_server_protocol_rekey_generate(server, ctx, TRUE);
- silc_server_packet_queue_purge(server, ctx->sock);
-
- /* The protocol ends in next stage. */
- protocol->state = SILC_PROTOCOL_STATE_END;
- }
-
- } else {
- /*
- * We are the initiator of this protocol
- */
-
- /* Start the re-key by sending the REKEY packet */
- silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY,
- 0, NULL, 0, FALSE);
-
- if (ctx->pfs == TRUE) {
- /*
- * Use Perfect Forward Secrecy, ie. negotiate the key material
- * using the SKE protocol.
- */
- ctx->ske = silc_ske_alloc(server->rng, server);
- ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
- silc_ske_group_get_by_number(idata->rekey->ske_group,
- &ctx->ske->prop->group);
-
- silc_ske_set_callbacks(ctx->ske,
- silc_server_protocol_rekey_send_packet,
- NULL, NULL, NULL, silc_ske_check_version,
- context);
-
- status = silc_ske_initiator_phase_2(ctx->ske, NULL, NULL, 0);
- if (status != SILC_SKE_STATUS_OK) {
- SILC_LOG_ERROR(("Error (%s) during Re-key (I PFS), with %s (%s)",
- silc_ske_map_status(status), ctx->sock->hostname,
- ctx->sock->ip));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- /* Advance the protocol state */
- protocol->state++;
- } else {
- /*
- * Do normal and simple re-key.
- */
-
- /* Send the REKEY_DONE to indicate we will take new keys into use
- now. */
- silc_server_packet_queue_purge(server, ctx->sock);
- silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
- 0, NULL, 0, FALSE);
-
- /* After we send REKEY_DONE we must set the sending encryption
- key to the new key since all packets after this packet must
- encrypted with the new key. */
- silc_server_protocol_rekey_generate(server, ctx, TRUE);
- silc_server_packet_queue_purge(server, ctx->sock);
-
- /* The protocol ends in next stage. */
- protocol->state = SILC_PROTOCOL_STATE_END;
- }
- }
- }
- break;
-
- case 2:
- /*
- * Second state, used only when doing re-key with PFS.
- */
- if (ctx->responder == TRUE) {
- if (ctx->pfs == TRUE) {
- /*
- * Send our KE packet to the initiator now that we've processed
- * the initiator's KE packet.
- */
- status = silc_ske_responder_finish(ctx->ske, NULL, NULL,
- SILC_SKE_PK_TYPE_SILC);
- if (status != SILC_SKE_STATUS_OK) {
- SILC_LOG_ERROR(("Error (%s) during Re-key (R PFS), with %s (%s)",
- silc_ske_map_status(status), ctx->sock->hostname,
- ctx->sock->ip));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
- }
-
- } else {
- if (ctx->pfs == TRUE) {
- /*
- * The packet type must be KE packet
- */
- if (!ctx->packet) {
- SILC_LOG_ERROR(("Error during Re-key, with %s (%s)",
- ctx->sock->hostname, ctx->sock->ip));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
- SILC_LOG_ERROR(("Error during Re-key (I PFS): re-key state is "
- "incorrect (received %d, expected %d packet), "
- "with %s (%s)", ctx->packet->type,
- SILC_PACKET_KEY_EXCHANGE_2, ctx->sock->hostname,
- ctx->sock->ip));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer);
- if (status != SILC_SKE_STATUS_OK) {
- SILC_LOG_ERROR(("Error (%s) during Re-key (I PFS), with %s (%s)",
- silc_ske_map_status(status), ctx->sock->hostname,
- ctx->sock->ip));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
- }
- }
-
- /* Send the REKEY_DONE to indicate we will take new keys into use
- now. */
- silc_server_packet_queue_purge(server, ctx->sock);
- silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
- 0, NULL, 0, FALSE);
-
- /* After we send REKEY_DONE we must set the sending encryption
- key to the new key since all packets after this packet must
- encrypted with the new key. */
- silc_server_protocol_rekey_generate_pfs(server, ctx, TRUE);
- silc_server_packet_queue_purge(server, ctx->sock);
-
- /* The protocol ends in next stage. */
- protocol->state = SILC_PROTOCOL_STATE_END;
- break;
-
- case SILC_PROTOCOL_STATE_END:
- /*
- * End protocol
- */
-
- if (!ctx->packet) {
- SILC_LOG_ERROR(("Error during Re-key, with %s (%s)",
- ctx->sock->hostname, ctx->sock->ip));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- if (ctx->packet->type != SILC_PACKET_REKEY_DONE) {
- SILC_LOG_ERROR(("Error during Re-key (%s PFS): re-key state is "
- "incorrect (received %d, expected %d packet), "
- "with %s (%s)", ctx->responder ? "R" : "I",
- ctx->packet->type, SILC_PACKET_REKEY_DONE,
- ctx->sock->hostname, ctx->sock->ip));
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute(protocol, server->schedule, 0, 300000);
- return;
- }
-
- /* We received the REKEY_DONE packet and all packets after this is
- encrypted with the new key so set the decryption key to the new key */
- if (ctx->pfs == TRUE)
- silc_server_protocol_rekey_generate_pfs(server, ctx, FALSE);
- else
- silc_server_protocol_rekey_generate(server, ctx, FALSE);
- silc_server_packet_queue_purge(server, ctx->sock);
-
- /* Assure that after calling final callback there cannot be pending
- executions for this protocol anymore. This just unregisters any
- timeout callbacks for this protocol. */
- silc_protocol_cancel(protocol, server->schedule);
-
- /* Protocol has ended, call the final callback */
- if (protocol->final_callback)
- silc_protocol_execute_final(protocol, server->schedule);
- else
- silc_protocol_free(protocol);
- break;
-
- case SILC_PROTOCOL_STATE_ERROR:
- /*
- * Error occured
- */
-
- if (ctx->pfs == TRUE)
- /* Send abort notification */
- silc_ske_abort(ctx->ske, ctx->ske->status);
-
- /* Assure that after calling final callback there cannot be pending
- executions for this protocol anymore. This just unregisters any
- timeout callbacks for this protocol. */
- silc_protocol_cancel(protocol, server->schedule);
-
- /* On error the final callback is always called. */
- if (protocol->final_callback)
- silc_protocol_execute_final(protocol, server->schedule);
- else
- silc_protocol_free(protocol);
- break;
-
- case SILC_PROTOCOL_STATE_FAILURE:
- /*
- * We have received failure from remote
- */
-
- SILC_LOG_ERROR(("Error during Re-Key: received Failure"));
-
- /* Assure that after calling final callback there cannot be pending
- executions for this protocol anymore. This just unregisters any
- timeout callbacks for this protocol. */
- silc_protocol_cancel(protocol, server->schedule);
-
- /* On error the final callback is always called. */
- if (protocol->final_callback)
- silc_protocol_execute_final(protocol, server->schedule);
- else
- silc_protocol_free(protocol);
- break;
-
- case SILC_PROTOCOL_STATE_UNKNOWN:
- break;
- }
-
-}
-
-/* Registers protocols used in server. */
-
-void silc_server_protocols_register(void)
-{
- silc_protocol_register(SILC_PROTOCOL_SERVER_CONNECTION_AUTH,
- silc_server_protocol_connection_auth);
- silc_protocol_register(SILC_PROTOCOL_SERVER_KEY_EXCHANGE,
- silc_server_protocol_key_exchange);
- silc_protocol_register(SILC_PROTOCOL_SERVER_REKEY,
- silc_server_protocol_rekey);
- silc_protocol_register(SILC_PROTOCOL_SERVER_BACKUP,
- silc_server_protocol_backup);
-}
-
-/* Unregisters protocols */
-
-void silc_server_protocols_unregister(void)
-{
- silc_protocol_unregister(SILC_PROTOCOL_SERVER_CONNECTION_AUTH,
- silc_server_protocol_connection_auth);
- silc_protocol_unregister(SILC_PROTOCOL_SERVER_KEY_EXCHANGE,
- silc_server_protocol_key_exchange);
- silc_protocol_unregister(SILC_PROTOCOL_SERVER_REKEY,
- silc_server_protocol_rekey);
- silc_protocol_unregister(SILC_PROTOCOL_SERVER_BACKUP,
- silc_server_protocol_backup);
-}
+++ /dev/null
-/*
-
- protocol.h
-
- Author: Pekka Riikonen <priikone@silcnet.org>
-
- Copyright (C) 1997 - 2003 Pekka Riikonen
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
-*/
-
-#ifndef PROTOCOL_H
-#define PROTOCOL_H
-
-/* SILC client protocol types */
-#define SILC_PROTOCOL_SERVER_NONE 0
-#define SILC_PROTOCOL_SERVER_CONNECTION_AUTH 1
-#define SILC_PROTOCOL_SERVER_KEY_EXCHANGE 2
-#define SILC_PROTOCOL_SERVER_REKEY 3
-#define SILC_PROTOCOL_SERVER_BACKUP 4
-/* #define SILC_PROTOCOL_SERVER_MAX 255 */
-
-/* Internal context for Key Exchange protocol. */
-typedef struct {
- void *server;
- void *context;
- SilcSocketConnection sock;
- SilcRng rng;
-
- /* TRUE if we are receiveing part of the protocol */
- bool responder;
-
- /* Destinations ID taken from authenticataed packet so that we can
- get the destinations ID. */
- void *dest_id;
- SilcIdType dest_id_type;
-
- /* Pointers to the configurations. Defined only when responder is TRUE */
- SilcServerConfigRef cconfig;
- SilcServerConfigRef sconfig;
- SilcServerConfigRef rconfig;
-
- SilcTask timeout_task;
- SilcPacketContext *packet;
- SilcSKESecurityPropertyFlag flags;
- SilcSKE ske;
- SilcSKEKeyMaterial *keymat;
-} SilcServerKEInternalContext;
-
-/* Internal context for connection authentication protocol */
-typedef struct {
- void *server;
- void *context;
- SilcSocketConnection sock;
-
- /* TRUE if we are receiving part of the protocol */
- bool responder;
-
- /* SKE object from Key Exchange protocol. */
- SilcSKE ske;
-
- /* Authentication method and data if we alreay know it. This is filled
- before starting the protocol if we know the authentication data.
- Otherwise these are and remain NULL. Used when we are initiating. */
- SilcUInt32 auth_meth;
- void *auth_data;
- SilcUInt32 auth_data_len;
-
- /* Destinations ID from KE protocol context */
- void *dest_id;
- SilcIdType dest_id_type;
-
- /* Pointers to the configurations. Defined only when responder is TRUE */
- SilcServerConfigRef cconfig;
- SilcServerConfigRef sconfig;
- SilcServerConfigRef rconfig;
-
- SilcTask timeout_task;
- SilcPacketContext *packet;
- SilcUInt16 conn_type;
-} SilcServerConnAuthInternalContext;
-
-/* Internal context for the rekey protocol */
-typedef struct {
- void *server;
- void *context;
- SilcSocketConnection sock;
- bool responder; /* TRUE if we are receiving party */
- bool pfs; /* TRUE if PFS is to be used */
- SilcSKE ske; /* Defined if PFS is used */
- SilcPacketContext *packet;
- SilcTask timeout_task;
-} SilcServerRekeyInternalContext;
-
-/* Prototypes */
-void silc_server_protocols_register(void);
-void silc_server_protocols_unregister(void);
-int silc_server_protocol_ke_set_keys(SilcServer server,
- SilcSKE ske,
- SilcSocketConnection sock,
- SilcSKEKeyMaterial *keymat,
- SilcCipher cipher,
- SilcPKCS pkcs,
- SilcHash hash,
- SilcHmac hmac,
- SilcSKEDiffieHellmanGroup group,
- bool is_responder);
-
-#endif
If we are normal server then this just returns our primary route. If
we are router we will do route lookup. */
-SilcSocketConnection silc_server_route_get(SilcServer server, void *id,
+SilcPacketStream silc_server_route_get(SilcServer server, void *id,
SilcIdType id_type)
{
if (server->server_type == SILC_ROUTER) {
router = silc_server_route_check(dest, port);
if (router)
- return (SilcSocketConnection)router->connection;
+ return router->connection;
}
return (server->id_entry->router)
- ? (SilcSocketConnection)server->id_entry->router->connection
+ ? server->id_entry->router->connection
: NULL;
}
SilcServerEntry router);
SilcServerEntry silc_server_route_check(SilcUInt32 dest,
SilcUInt16 port);
-SilcSocketConnection silc_server_route_get(SilcServer server, void *id,
+SilcPacketStream silc_server_route_get(SilcServer server, void *id,
SilcIdType id_type);
#endif
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2005, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
GNU General Public License for more details.
*/
-/*
- * This is the actual SILC server than handles everything relating to
- * servicing the SILC connections. This is also a SILC router as a router
- * is also normal server.
- */
-/* $Id$ */
#include "serverincludes.h"
#include "server_internal.h"
-/* Static prototypes */
-SILC_TASK_CALLBACK(silc_server_rehash_close_connection);
-SILC_TASK_CALLBACK(silc_server_connect_to_router_retry);
-SILC_TASK_CALLBACK(silc_server_connect_router);
-SILC_TASK_CALLBACK(silc_server_connect_to_router_second);
-SILC_TASK_CALLBACK(silc_server_connect_to_router_final);
-SILC_TASK_CALLBACK(silc_server_accept_new_connection);
-SILC_TASK_CALLBACK(silc_server_accept_new_connection_second);
-SILC_TASK_CALLBACK(silc_server_accept_new_connection_final);
-SILC_TASK_CALLBACK(silc_server_packet_process);
-SILC_TASK_CALLBACK(silc_server_packet_parse_real);
-SILC_TASK_CALLBACK(silc_server_close_connection_final);
-SILC_TASK_CALLBACK(silc_server_free_client_data_timeout);
-SILC_TASK_CALLBACK(silc_server_timeout_remote);
-SILC_TASK_CALLBACK(silc_server_channel_key_rekey);
+/************************* Types and definitions ***************************/
+
SILC_TASK_CALLBACK(silc_server_get_stats);
SILC_TASK_CALLBACK(silc_server_connect_router);
+SILC_TASK_CALLBACK(silc_server_do_rekey);
+static void silc_server_accept_new_connection(SilcNetStatus status,
+ SilcStream stream,
+ void *context);
+static void silc_server_packet_parse_type(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacket packet);
-/* Allocates a new SILC server object. This has to be done before the server
- can be used. After allocation one must call silc_server_init to initialize
- the server. The new allocated server object is returned to the new_server
- argument. */
-
-int silc_server_alloc(SilcServer *new_server)
-{
- SilcServer server;
-
- SILC_LOG_DEBUG(("Allocating new server object"));
-
- server = silc_calloc(1, sizeof(*server));
- server->server_type = SILC_SERVER;
- server->standalone = TRUE;
- server->local_list = silc_calloc(1, sizeof(*server->local_list));
- server->global_list = silc_calloc(1, sizeof(*server->global_list));
- server->pending_commands = silc_dlist_init();
-#ifdef SILC_SIM
- server->sim = silc_dlist_init();
-#endif
-
- *new_server = server;
- return TRUE;
-}
+/************************ Static utility functions **************************/
-/* Free's the SILC server object. This is called at the very end before
- the program ends. */
+/* SKE public key verification callback */
-void silc_server_free(SilcServer server)
+static void
+silc_server_verify_key(SilcSKE ske,
+ SilcPublicKey public_key,
+ void *context,
+ SilcSKEVerifyCbCompletion completion,
+ void *completion_context)
{
- SilcIDCacheList list;
- SilcIDCacheEntry cache;
+ SilcPacketStream sock = context;
+ SilcUnknownEntry entry = silc_packet_get_context(sock);
- if (!server)
- return;
+ SILC_LOG_DEBUG(("Verifying public key"));
-#ifdef SILC_SIM
- {
- SilcSim sim;
- silc_dlist_start(server->sim);
- while ((sim = silc_dlist_get(server->sim)) != SILC_LIST_END) {
- silc_dlist_del(server->sim, sim);
- silc_sim_close(sim);
- silc_sim_free(sim);
- }
- silc_dlist_uninit(server->sim);
+ if (silc_pkcs_get_type(public_key) != SILC_SKE_PK_TYPE_SILC) {
+ SILC_LOG_WARNING(("We don't support %s (%s) port %d public key type %d",
+ entry->hostname, entry->ip, entry->port,
+ silc_pkcs_get_type(public_key)));
+ completion(ske, SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
+ completion_context);
+ return;
}
-#endif
- silc_server_backup_free(server);
- silc_server_config_unref(&server->config_ref);
- if (server->rng)
- silc_rng_free(server->rng);
- if (server->pkcs)
- silc_pkcs_free(server->pkcs);
- if (server->public_key)
- silc_pkcs_public_key_free(server->public_key);
- if (server->private_key)
- silc_pkcs_private_key_free(server->private_key);
- if (server->pending_commands)
- silc_dlist_uninit(server->pending_commands);
- if (server->id_entry)
- silc_idlist_del_server(server->local_list, server->id_entry);
+ /* We accept all keys without explicit verification */
+ completion(ske, SILC_SKE_STATUS_OK, completion_context);
+}
- /* Delete all channels */
- list = NULL;
- if (silc_idcache_get_all(server->local_list->channels, &list) &&
- silc_idcache_list_first(list, &cache)) {
- silc_idlist_del_channel(server->local_list, cache->context);
- while (silc_idcache_list_next(list, &cache))
- silc_idlist_del_channel(server->local_list, cache->context);
- }
- if (list)
- silc_idcache_list_free(list);
- list = NULL;
- if (silc_idcache_get_all(server->global_list->channels, &list) &&
- silc_idcache_list_first(list, &cache)) {
- silc_idlist_del_channel(server->global_list, cache->context);
- while (silc_idcache_list_next(list, &cache))
- silc_idlist_del_channel(server->global_list, cache->context);
- }
- if (list)
- silc_idcache_list_free(list);
- if (server->pk_hash)
- silc_hash_table_free(server->pk_hash);
+/************************ Packet engine callbacks ***************************/
- /* Delete all clients */
- list = NULL;
- if (silc_idcache_get_all(server->local_list->clients, &list) &&
- silc_idcache_list_first(list, &cache)) {
- silc_idlist_del_client(server->local_list, cache->context);
- while (silc_idcache_list_next(list, &cache))
- silc_idlist_del_client(server->local_list, cache->context);
- }
- if (list)
- silc_idcache_list_free(list);
- list = NULL;
- if (silc_idcache_get_all(server->global_list->clients, &list) &&
- silc_idcache_list_first(list, &cache)) {
- silc_idlist_del_client(server->global_list, cache->context);
- while (silc_idcache_list_next(list, &cache))
- silc_idlist_del_client(server->global_list, cache->context);
- }
- if (list)
- silc_idcache_list_free(list);
+/* Packet engine callback to receive a packet */
+static SilcBool silc_server_packet_receive(SilcPacketEngine engine,
+ SilcPacketStream stream,
+ SilcPacket packet,
+ void *callback_context,
+ void *stream_context)
+{
+ SilcServer server = callback_context;
+ SilcIDListData idata = stream_context;
- /* Delete all servers */
- list = NULL;
- if (silc_idcache_get_all(server->local_list->servers, &list) &&
- silc_idcache_list_first(list, &cache)) {
- silc_idlist_del_server(server->local_list, cache->context);
- while (silc_idcache_list_next(list, &cache))
- silc_idlist_del_server(server->local_list, cache->context);
- }
- if (list)
- silc_idcache_list_free(list);
- list = NULL;
- if (silc_idcache_get_all(server->global_list->servers, &list) &&
- silc_idcache_list_first(list, &cache)) {
- silc_idlist_del_server(server->global_list, cache->context);
- while (silc_idcache_list_next(list, &cache))
- silc_idlist_del_server(server->global_list, cache->context);
+ /* Packets we do not handle */
+ switch (packet->type) {
+ case SILC_PACKET_HEARTBEAT:
+ case SILC_PACKET_SUCCESS:
+ case SILC_PACKET_FAILURE:
+ case SILC_PACKET_REJECT:
+ case SILC_PACKET_KEY_EXCHANGE:
+ case SILC_PACKET_KEY_EXCHANGE_1:
+ case SILC_PACKET_KEY_EXCHANGE_2:
+ case SILC_PACKET_REKEY_DONE:
+ case SILC_PACKET_CONNECTION_AUTH:
+ return FALSE;
+ break;
}
- if (list)
- silc_idcache_list_free(list);
- silc_idcache_free(server->local_list->clients);
- silc_idcache_free(server->local_list->servers);
- silc_idcache_free(server->local_list->channels);
- silc_idcache_free(server->global_list->clients);
- silc_idcache_free(server->global_list->servers);
- silc_idcache_free(server->global_list->channels);
- silc_hash_table_free(server->watcher_list);
- silc_hash_table_free(server->watcher_list_pk);
+ /* Only specific packets can come without source ID present. */
+ if ((!packet->src_id ||
+ !(idata->status & SILC_IDLIST_STATUS_REGISTERED)) &&
+ packet->type != SILC_PACKET_NEW_CLIENT &&
+ packet->type != SILC_PACKET_NEW_SERVER &&
+ packet->type != SILC_PACKET_DISCONNECT)
+ return FALSE;
- silc_hash_free(server->md5hash);
- silc_hash_free(server->sha1hash);
- silc_hmac_unregister_all();
- silc_hash_unregister_all();
- silc_cipher_unregister_all();
- silc_pkcs_unregister_all();
+ /* NEW_CLIENT and NEW_SERVER are accepted only without source ID
+ and for unregistered connection. */
+ if (packet->src_id && (packet->type == SILC_PACKET_NEW_CLIENT ||
+ packet->type == SILC_PACKET_NEW_SERVER) &&
+ (idata->status & SILC_IDLIST_STATUS_REGISTERED))
+ return FALSE;
- silc_free(server->local_list);
- silc_free(server->global_list);
- silc_free(server->server_name);
- silc_free(server->id_string);
- silc_free(server->purge_i);
- silc_free(server->purge_g);
- silc_free(server);
+ /* Process packet */
+ silc_server_packet_parse_type(server, stream, packet);
+
+ return TRUE;
}
-/* Creates a new server listener. */
+/* Packet engine callback to indicate end of stream */
-static bool silc_server_listen(SilcServer server, const char *server_ip,
- SilcUInt16 port, int *sock)
+static void silc_server_packet_eos(SilcPacketEngine engine,
+ SilcPacketStream stream,
+ void *callback_context,
+ void *stream_context)
{
- *sock = silc_net_create_server(port, server_ip);
- if (*sock < 0) {
- SILC_SERVER_LOG_ERROR(("Could not create server listener: %s on %hu",
- server_ip, port));
- return FALSE;
- }
- return TRUE;
+ SILC_LOG_DEBUG(("End of stream received"));
}
-/* Adds a secondary listener. */
+/* Packet engine callback to indicate error */
-bool silc_server_init_secondary(SilcServer server)
+static void silc_server_packet_error(SilcPacketEngine engine,
+ SilcPacketStream stream,
+ SilcPacketError error,
+ void *callback_context,
+ void *stream_context)
{
- int sock = 0, sock_list[server->config->param.connections_max];
- SilcSocketConnection newsocket = NULL;
- SilcServerConfigServerInfoInterface *interface;
- for (interface = server->config->server_info->secondary; interface;
- interface = interface->next, sock++) {
+}
- if (!silc_server_listen(server,
- interface->server_ip, interface->port, &sock_list[sock]))
- goto err;
+/* Packet stream callbacks */
+static SilcPacketCallbacks silc_server_stream_cbs =
+{
+ silc_server_packet_receive,
+ silc_server_packet_eos,
+ silc_server_packet_error
+};
- /* Set socket to non-blocking mode */
- silc_net_set_socket_nonblock(sock_list[sock]);
+/* Parses the packet type and calls what ever routines the packet type
+ requires. This is done for all incoming packets. */
- /* Add ourselves also to the socket table. The entry allocated above
- is sent as argument for fast referencing in the future. */
- silc_socket_alloc(sock_list[sock],
- SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
- server->sockets[sock_list[sock]] = newsocket;
- SILC_SET_LISTENER(newsocket);
+static void silc_server_packet_parse_type(SilcServer server,
+ SilcPacketStream sock,
+ SilcPacket packet)
+{
+ SilcPacketType type = packet->type;
+ SilcIDListData idata = silc_packet_get_context(sock);
- /* Perform name and address lookups to resolve the listenning address
- and port. */
- if (!silc_net_check_local_by_sock(sock_list[sock], &newsocket->hostname,
- &newsocket->ip)) {
- if ((server->config->require_reverse_lookup && !newsocket->hostname) ||
- !newsocket->ip) {
- SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
- newsocket->hostname ? newsocket->hostname :
- newsocket->ip ? newsocket->ip : ""));
- server->stat.conn_failures++;
- goto err;
- }
- if (!newsocket->hostname)
- newsocket->hostname = strdup(newsocket->ip);
- }
- newsocket->port = silc_net_get_local_port(sock);
+ SILC_LOG_DEBUG(("Received %s packet [flags %d]",
+ silc_get_packet_name(type), packet->flags));
- newsocket->user_data = (void *)server->id_entry;
- silc_schedule_task_add(server->schedule, sock_list[sock],
- silc_server_accept_new_connection,
- (void *)server, 0, 0,
- SILC_TASK_FD,
- SILC_TASK_PRI_NORMAL);
- }
+ /* Parse the packet type */
+ switch (type) {
+ case SILC_PACKET_NOTIFY:
+ /*
+ * Received notify packet. Server can receive notify packets from
+ * router. Server then relays the notify messages to clients if needed.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ silc_server_notify_list(server, sock, packet);
+ else
+ silc_server_notify(server, sock, packet);
+ break;
- return TRUE;
+ /*
+ * Private Message packets
+ */
+ case SILC_PACKET_PRIVATE_MESSAGE:
+ /*
+ * Received private message packet. The packet is coming from either
+ * client or server.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ idata->last_receive = time(NULL);
+ silc_server_private_message(server, sock, packet);
+ break;
- err:
- do silc_net_close_server(sock_list[sock--]); while (sock >= 0);
- return FALSE;
-}
+ /*
+ * Channel packets
+ */
+ case SILC_PACKET_CHANNEL_MESSAGE:
+ /*
+ * Received channel message. Channel messages are special packets
+ * (although probably most common ones) thus they are handled
+ * specially.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ idata->last_receive = time(NULL);
+ silc_server_channel_message(server, sock, packet);
+ break;
-/* Initializes the entire SILC server. This is called always before running
- the server. This is called only once at the initialization of the program.
- This binds the server to its listenning port. After this function returns
- one should call silc_server_run to start the server. This returns TRUE
- when everything is ok to run the server. Configuration file must be
- read and parsed before calling this. */
+ /*
+ * Command packets
+ */
+ case SILC_PACKET_COMMAND:
+ /*
+ * Recived command. Processes the command request and allocates the
+ * command context and calls the command.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ server->stat.commands_received++;
+ silc_server_command_process(server, sock, packet);
+ break;
-bool silc_server_init(SilcServer server)
-{
- int sock = -1;
- SilcServerID *id;
- SilcServerEntry id_entry;
- SilcIDListPurge purge;
- SilcSocketConnection newsocket = NULL;
+ case SILC_PACKET_COMMAND_REPLY:
+ /*
+ * Received command reply packet. Received command reply to command. It
+ * may be reply to command sent by us or reply to command sent by client
+ * that we've routed further.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ server->stat.commands_received++;
+ silc_server_command_reply(server, sock, packet);
+ break;
- SILC_LOG_DEBUG(("Initializing server"));
+ case SILC_PACKET_DISCONNECT:
+ {
+ SilcStatus status;
+ char *message = NULL;
- server->starttime = time(NULL);
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ if (silc_buffer_len(&packet->buffer) < 1)
+ break;
- /* Take config object for us */
- silc_server_config_ref(&server->config_ref, server->config,
- server->config);
+ status = (SilcStatus)packet->buffer.data[0];
+ if (silc_buffer_len(&packet->buffer) > 1 &&
+ silc_utf8_valid(packet->buffer.data + 1, silc_buffer_len(&packet->buffer) - 1))
+ message = silc_memdup(packet->buffer.data + 1,
+ silc_buffer_len(&packet->buffer) - 1);
-#ifdef SILC_DEBUG
- /* Set debugging on if configured */
- if (server->config->debug_string) {
- silc_log_debug(TRUE);
- silc_log_set_debug_string(server->config->debug_string);
- }
-#endif /* SILC_DEBUG */
+#if 0
+ SILC_LOG_INFO(("Disconnected by %s (%s): %s (%d) %s",
+ sock->ip, sock->hostname,
+ silc_get_status_message(status), status,
+ message ? message : ""));
+#endif
+ silc_free(message);
- /* Steal public and private key from the config object */
- server->public_key = server->config->server_info->public_key;
- server->private_key = server->config->server_info->private_key;
- server->config->server_info->public_key = NULL;
- server->config->server_info->private_key = NULL;
-
- /* Register all configured ciphers, PKCS and hash functions. */
- if (!silc_server_config_register_ciphers(server))
- silc_cipher_register_default();
- if (!silc_server_config_register_pkcs(server))
- silc_pkcs_register_default();
- if (!silc_server_config_register_hashfuncs(server))
- silc_hash_register_default();
- if (!silc_server_config_register_hmacs(server))
- silc_hmac_register_default();
-
- /* Initialize random number generator for the server. */
- server->rng = silc_rng_alloc();
- silc_rng_init(server->rng);
- silc_rng_global_init(server->rng);
-
- /* Initialize hash functions for server to use */
- silc_hash_alloc("md5", &server->md5hash);
- silc_hash_alloc("sha1", &server->sha1hash);
-
- /* Allocate PKCS context for local public and private keys */
- if (!silc_pkcs_alloc(server->public_key->name, &server->pkcs))
- goto err;
- silc_pkcs_public_key_set(server->pkcs, server->public_key);
- silc_pkcs_private_key_set(server->pkcs, server->private_key);
-
- /* Initialize the scheduler */
- server->schedule = silc_schedule_init(server->config->param.connections_max,
- server);
- if (!server->schedule)
- goto err;
-
- /* First, register log files configuration for error output */
- silc_server_config_setlogfiles(server);
-
- /* Initialize ID caches */
- server->local_list->clients =
- silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor,
- server, FALSE, TRUE);
- server->local_list->servers =
- silc_idcache_alloc(0, SILC_ID_SERVER, NULL, NULL, FALSE, TRUE);
- server->local_list->channels =
- silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, NULL, FALSE, TRUE);
-
- /* These are allocated for normal server as well as these hold some
- global information that the server has fetched from its router. For
- router these are used as they are supposed to be used on router. */
- server->global_list->clients =
- silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor,
- server, FALSE, TRUE);
- server->global_list->servers =
- silc_idcache_alloc(0, SILC_ID_SERVER, NULL, NULL, FALSE, TRUE);
- server->global_list->channels =
- silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, NULL, FALSE, TRUE);
-
- /* Init watcher lists */
- server->watcher_list =
- silc_hash_table_alloc(1, silc_hash_client_id_hash, NULL,
- silc_hash_data_compare, (void *)CLIENTID_HASH_LEN,
- NULL, NULL, TRUE);
- if (!server->watcher_list)
- goto err;
- server->watcher_list_pk =
- silc_hash_table_alloc(1, silc_hash_public_key, NULL,
- silc_hash_public_key_compare, NULL,
- NULL, NULL, TRUE);
- if (!server->watcher_list_pk)
- goto err;
-
- /* Init public key list */
- server->pk_hash =
- silc_hash_table_alloc(0, silc_hash_public_key, NULL,
- silc_hash_public_key_compare, NULL,
- NULL, NULL, TRUE);
-
- if (!server->pk_hash)
- goto err;
+ /* Do not switch to backup in case of error */
+ server->backup_noswitch = (status == SILC_STATUS_OK ? FALSE : TRUE);
- /* Create a listening server */
- if (!silc_server_listen(server,
- server->config->server_info->primary == NULL ? NULL :
- server->config->server_info->primary->server_ip,
- server->config->server_info->primary == NULL ? 0 :
- server->config->server_info->primary->port,
- &sock))
- goto err;
+ /* If backup disconnected then mark that resuming will not be allowed */
+#if 0
+ if (server->server_type == SILC_ROUTER && !server->backup_router &&
+ sock->type == SILC_CONN_SERVER && sock->user_data) {
+ SilcServerEntry server_entry = sock->user_data;
+ if (server_entry->server_type == SILC_BACKUP_ROUTER)
+ server->backup_closed = TRUE;
+ }
- /* Set socket to non-blocking mode */
- silc_net_set_socket_nonblock(sock);
- server->sock = sock;
+ /* Handle the disconnection from our end too */
+ if (sock->user_data && SILC_IS_LOCAL(sock->user_data))
+ silc_server_free_sock_user_data(server, sock, NULL);
+ SILC_SET_DISCONNECTING(sock);
+ silc_server_close_connection(server, sock);
+ server->backup_noswitch = FALSE;
+#endif
+ }
+ break;
- /* Allocate the entire socket list that is used in server. Eventually
- all connections will have entry in this table (it is a table of
- pointers to the actual object that is allocated individually
- later). */
- server->sockets = silc_calloc(server->config->param.connections_max,
- sizeof(*server->sockets));
- if (!server->sockets)
- goto err;
+ case SILC_PACKET_CHANNEL_KEY:
+ /*
+ * Received key for channel. As channels are created by the router
+ * the keys are as well. We will distribute the key to all of our
+ * locally connected clients on the particular channel. Router
+ * never receives this channel and thus is ignored.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ silc_server_channel_key(server, sock, packet);
+ break;
- /* Add ourselves also to the socket table. The entry allocated above
- is sent as argument for fast referencing in the future. */
- silc_socket_alloc(sock, SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
- server->sockets[sock] = newsocket;
- SILC_SET_LISTENER(newsocket);
+ case SILC_PACKET_PRIVATE_MESSAGE_KEY:
+ /*
+ * Private message key packet.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ silc_server_private_message_key(server, sock, packet);
+ break;
- /* Perform name and address lookups to resolve the listenning address
- and port. */
- if (!silc_net_check_local_by_sock(sock, &newsocket->hostname,
- &newsocket->ip)) {
- if ((server->config->require_reverse_lookup && !newsocket->hostname) ||
- !newsocket->ip) {
- SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
- newsocket->hostname ? newsocket->hostname :
- newsocket->ip ? newsocket->ip : ""));
- server->stat.conn_failures++;
- goto err;
- }
- if (!newsocket->hostname)
- newsocket->hostname = strdup(newsocket->ip);
- }
- newsocket->port = silc_net_get_local_port(sock);
+ case SILC_PACKET_CONNECTION_AUTH_REQUEST:
+ /*
+ * Connection authentication request packet. When we receive this packet
+ * we will send to the other end information about our mandatory
+ * authentication method for the connection. This packet maybe received
+ * at any time.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ silc_server_connection_auth_request(server, sock, packet);
+ break;
- /* Create a Server ID for the server. */
- silc_id_create_server_id(newsocket->ip, newsocket->port, server->rng, &id);
- if (!id)
- goto err;
+ case SILC_PACKET_NEW_ID:
+ /*
+ * Received New ID packet. This includes some new ID that has been
+ * created. It may be for client, server or channel. This is the way
+ * to distribute information about new registered entities in the
+ * SILC network.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ silc_server_new_id_list(server, sock, packet);
+ else
+ silc_server_new_id(server, sock, packet);
+ break;
- server->id = id;
- server->id_string = silc_id_id2str(id, SILC_ID_SERVER);
- server->id_string_len = silc_id_get_len(id, SILC_ID_SERVER);
- server->server_name = server->config->server_info->server_name;
- server->config->server_info->server_name = NULL;
+ case SILC_PACKET_NEW_CLIENT:
+ /*
+ * Received new client packet. This includes client information that
+ * we will use to create initial client ID. After creating new
+ * ID we will send it to the client.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ silc_server_new_client(server, sock, packet);
+ break;
- /* Add ourselves to the server list. We don't have a router yet
- beacuse we haven't established a route yet. It will be done later.
- For now, NULL is sent as router. This allocates new entry to
- the ID list. */
- id_entry =
- silc_idlist_add_server(server->local_list, strdup(server->server_name),
- server->server_type, server->id, NULL, NULL);
- if (!id_entry) {
- SILC_LOG_ERROR(("Could not add ourselves to cache"));
- goto err;
- }
- id_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
+ case SILC_PACKET_NEW_SERVER:
+ /*
+ * Received new server packet. This includes Server ID and some other
+ * information that we may save. This is received after server has
+ * connected to us.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ silc_server_new_server(server, sock, packet);
+ break;
- /* Put the allocated socket pointer also to the entry allocated above
- for fast back-referencing to the socket list. */
- newsocket->user_data = (void *)id_entry;
- id_entry->connection = (void *)newsocket;
- server->id_entry = id_entry;
+ case SILC_PACKET_NEW_CHANNEL:
+ /*
+ * Received new channel packet. Information about new channel in the
+ * network are distributed using this packet.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ silc_server_new_channel_list(server, sock, packet);
+ else
+ silc_server_new_channel(server, sock, packet);
+ break;
- /* Register protocols */
- silc_server_protocols_register();
+ case SILC_PACKET_HEARTBEAT:
+ /*
+ * Received heartbeat.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ break;
- /* Create connections to configured routers. */
- silc_server_create_connections(server);
+ case SILC_PACKET_KEY_AGREEMENT:
+ /*
+ * Received heartbeat.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ silc_server_key_agreement(server, sock, packet);
+ break;
- /* Add listener task to the scheduler. This task receives new connections
- to the server. This task remains on the queue until the end of the
- program. */
- silc_schedule_task_add(server->schedule, sock,
- silc_server_accept_new_connection,
- (void *)server, 0, 0,
- SILC_TASK_FD,
- SILC_TASK_PRI_NORMAL);
+ case SILC_PACKET_REKEY:
+ /*
+ * Received re-key packet. The sender wants to regenerate the session
+ * keys.
+ */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ /* XXX handle rekey */
+ break;
- if (silc_server_init_secondary(server) == FALSE)
- goto err;
+ case SILC_PACKET_FTP:
+ /* FTP packet */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ silc_server_ftp(server, sock, packet);
+ break;
- server->listenning = TRUE;
+ case SILC_PACKET_RESUME_CLIENT:
+ /* Resume client */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ silc_server_resume_client(server, sock, packet);
+ break;
- /* If server connections has been configured then we must be router as
- normal server cannot have server connections, only router connections. */
- if (server->config->servers) {
- SilcServerConfigServer *ptr = server->config->servers;
+ case SILC_PACKET_RESUME_ROUTER:
+ /* Resume router packet received. This packet is received for backup
+ router resuming protocol. */
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+#if 0
+ silc_server_backup_resume_router(server, sock, packet);
+#endif
+ break;
- server->server_type = SILC_ROUTER;
- while (ptr) {
- if (ptr->backup_router) {
- server->server_type = SILC_BACKUP_ROUTER;
- server->backup_router = TRUE;
- server->id_entry->server_type = SILC_BACKUP_ROUTER;
- break;
- }
- ptr = ptr->next;
- }
+ default:
+ SILC_LOG_ERROR(("Incorrect packet type %d, packet dropped", type));
+ break;
}
+}
- /* Register the ID Cache purge task. This periodically purges the ID cache
- and removes the expired cache entries. */
+/****************************** Server API **********************************/
- /* Clients local list */
- server->purge_i = purge = silc_calloc(1, sizeof(*purge));
- purge->cache = server->local_list->clients;
- purge->timeout = 600;
- silc_schedule_task_add(server->schedule, 0, silc_idlist_purge,
- (void *)purge, purge->timeout, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+/* Allocates a new SILC server object. This has to be done before the server
+ can be used. After allocation one must call silc_server_init to initialize
+ the server. The new allocated server object is returned to the new_server
+ argument. */
- /* Clients global list */
- server->purge_g = purge = silc_calloc(1, sizeof(*purge));
- purge->cache = server->global_list->clients;
- purge->timeout = 300;
- silc_schedule_task_add(server->schedule, 0, silc_idlist_purge,
- (void *)purge, purge->timeout, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+SilcBool silc_server_alloc(SilcServer *new_server)
+{
+ SilcServer server;
- /* If we are normal server we'll retrieve network statisticial information
- once in a while from the router. */
- if (server->server_type != SILC_ROUTER)
- silc_schedule_task_add(server->schedule, 0, silc_server_get_stats,
- server, 10, 0, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_LOW);
+ SILC_LOG_DEBUG(("Allocating new server object"));
- if (server->server_type == SILC_ROUTER)
- server->stat.routers++;
+ server = silc_calloc(1, sizeof(*server));
+ if (!server)
+ return FALSE;
+ server->server_type = SILC_SERVER;
+ server->standalone = TRUE;
+ server->local_list = silc_calloc(1, sizeof(*server->local_list));
+ if (!server->local_list)
+ return FALSE;
+ server->global_list = silc_calloc(1, sizeof(*server->global_list));
+ if (!server->global_list)
+ return FALSE;
+ server->pending_commands = silc_dlist_init();
+ if (!server->pending_commands)
+ return FALSE;
+ server->listeners = silc_dlist_init();
+ if (!server->listeners)
+ return FALSE;
+ server->repository = silc_skr_alloc();
+ if (!server->repository)
+ return FALSE;
- SILC_LOG_DEBUG(("Server initialized"));
+ *new_server = server;
- /* We are done here, return succesfully */
return TRUE;
-
- err:
- silc_server_config_unref(&server->config_ref);
- silc_net_close_server(sock);
- return FALSE;
}
-/* Task callback to close a socket connection after rehash */
+/* Free's the SILC server object. This is called at the very end before
+ the program ends. */
-SILC_TASK_CALLBACK(silc_server_rehash_close_connection)
+void silc_server_free(SilcServer server)
{
- SilcServer server = context;
- SilcSocketConnection sock = server->sockets[fd];
+ SilcList list;
+ SilcIDCacheEntry cache;
- if (!sock)
+ if (!server)
return;
- SILC_LOG_INFO(("Connection %s:%d [%s] is unconfigured",
- sock->hostname, sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
- silc_schedule_task_del_by_context(server->schedule, sock);
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_BANNED_FROM_SERVER,
- "This connection is removed from "
- "configuration");
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
-}
-
-/* This function basically reads the config file again and switches the config
- object pointed by the server object. After that, we have to fix various
- things such as the server_name and the listening ports.
- Keep in mind that we no longer have the root privileges at this point. */
-
-bool silc_server_rehash(SilcServer server)
-{
- SilcServerConfig newconfig;
-
- SILC_LOG_INFO(("Rehashing server"));
-
- /* Reset the logging system */
- silc_log_quick(TRUE);
- silc_log_flush_all();
+ silc_server_backup_free(server);
+ silc_server_config_unref(&server->config_ref);
+ if (server->pk_hash)
+ silc_hash_table_free(server->pk_hash);
+ if (server->rng)
+ silc_rng_free(server->rng);
+ if (server->public_key)
+ silc_pkcs_public_key_free(server->public_key);
+ if (server->private_key)
+ silc_pkcs_private_key_free(server->private_key);
+ if (server->pending_commands)
+ silc_dlist_uninit(server->pending_commands);
+ if (server->id_entry)
+ silc_idlist_del_server(server->local_list, server->id_entry);
- /* Start the main rehash phase (read again the config file) */
- newconfig = silc_server_config_alloc(server->config_file);
- if (!newconfig) {
- SILC_LOG_ERROR(("Rehash FAILED."));
- return FALSE;
+ /* Delete all channels */
+ if (silc_idcache_get_all(server->local_list->channels, &list)) {
+ silc_list_start(list);
+ while ((cache = silc_list_get(list)))
+ silc_idlist_del_channel(server->local_list, cache->context);
}
-
- /* Reinit scheduler if necessary */
- if (newconfig->param.connections_max > server->config->param.connections_max)
- if (!silc_schedule_reinit(server->schedule,
- newconfig->param.connections_max))
- return FALSE;
-
- /* Fix the server_name field */
- if (strcmp(server->server_name, newconfig->server_info->server_name)) {
- silc_free(server->server_name);
-
- /* Check server name */
- server->server_name =
- silc_identifier_check(newconfig->server_info->server_name,
- strlen(newconfig->server_info->server_name),
- SILC_STRING_LOCALE, 256, NULL);
- if (!server->server_name) {
- SILC_LOG_ERROR(("Malformed server name string '%s'",
- server->config->server_info->server_name));
- return FALSE;
- }
-
- /* Update the idcache list with a fresh pointer */
- silc_free(server->id_entry->server_name);
- server->id_entry->server_name = strdup(server->server_name);
- if (!silc_idcache_del_by_context(server->local_list->servers,
- server->id_entry))
- return FALSE;
- if (!silc_idcache_add(server->local_list->servers,
- strdup(server->id_entry->server_name),
- server->id_entry->id, server->id_entry, 0, NULL))
- return FALSE;
+ if (silc_idcache_get_all(server->global_list->channels, &list)) {
+ silc_list_start(list);
+ while ((cache = silc_list_get(list)))
+ silc_idlist_del_channel(server->global_list, cache->context);
}
- /* Set logging */
- silc_server_config_setlogfiles(server);
-
- /* Change new key pair if necessary */
- if (newconfig->server_info->public_key &&
- !silc_pkcs_public_key_compare(server->public_key,
- newconfig->server_info->public_key)) {
- silc_pkcs_public_key_free(server->public_key);
- silc_pkcs_private_key_free(server->private_key);
- server->public_key = newconfig->server_info->public_key;
- server->private_key = newconfig->server_info->private_key;
- newconfig->server_info->public_key = NULL;
- newconfig->server_info->private_key = NULL;
-
- /* Allocate PKCS context for local public and private keys */
- silc_pkcs_free(server->pkcs);
- if (!silc_pkcs_alloc(server->public_key->name, &server->pkcs))
- return FALSE;
- silc_pkcs_public_key_set(server->pkcs, server->public_key);
- silc_pkcs_private_key_set(server->pkcs, server->private_key);
+ /* Delete all clients */
+ if (silc_idcache_get_all(server->local_list->clients, &list)) {
+ silc_list_start(list);
+ while ((cache = silc_list_get(list)))
+ silc_idlist_del_client(server->local_list, cache->context);
+ }
+ if (silc_idcache_get_all(server->global_list->clients, &list)) {
+ silc_list_start(list);
+ while ((cache = silc_list_get(list)))
+ silc_idlist_del_client(server->global_list, cache->context);
}
- /* Check for unconfigured server and router connections and close
- connections that were unconfigured. */
+ /* Delete all servers */
+ if (silc_idcache_get_all(server->local_list->servers, &list)) {
+ silc_list_start(list);
+ while ((cache = silc_list_get(list)))
+ silc_idlist_del_server(server->local_list, cache->context);
+ }
+ if (silc_idcache_get_all(server->global_list->servers, &list)) {
+ while ((cache = silc_list_get(list)))
+ silc_idlist_del_server(server->global_list, cache->context);
+ }
- if (server->config->routers) {
- SilcServerConfigRouter *ptr;
- SilcServerConfigRouter *newptr;
- bool found;
+ silc_idcache_free(server->local_list->clients);
+ silc_idcache_free(server->local_list->servers);
+ silc_idcache_free(server->local_list->channels);
+ silc_idcache_free(server->global_list->clients);
+ silc_idcache_free(server->global_list->servers);
+ silc_idcache_free(server->global_list->channels);
+ silc_hash_table_free(server->watcher_list);
+ silc_hash_table_free(server->watcher_list_pk);
- for (ptr = server->config->routers; ptr; ptr = ptr->next) {
- found = FALSE;
+ silc_hash_free(server->md5hash);
+ silc_hash_free(server->sha1hash);
+ silc_hmac_unregister_all();
+ silc_hash_unregister_all();
+ silc_cipher_unregister_all();
+ silc_pkcs_unregister_all();
- /* Check whether new config has this one too */
- for (newptr = newconfig->routers; newptr; newptr = newptr->next) {
- if (silc_string_compare(newptr->host, ptr->host) &&
- newptr->port == ptr->port &&
- newptr->initiator == ptr->initiator) {
- found = TRUE;
- break;
- }
- }
+ silc_free(server->local_list);
+ silc_free(server->global_list);
+ silc_free(server->server_name);
+ silc_free(server->id_string);
+ silc_free(server->purge_i);
+ silc_free(server->purge_g);
+ silc_free(server);
+}
- if (!found && ptr->host) {
- /* Remove this connection */
- SilcSocketConnection sock;
- sock = silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_ROUTER,
- ptr->host, ptr->port);
- if (sock && !SILC_IS_LISTENER(sock))
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rehash_close_connection,
- server, 0, 1, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- }
- }
+/* Creates a new server listener. */
+
+static SilcNetListener
+silc_server_listen(SilcServer server, const char *server_ip, SilcUInt16 port)
+{
+ SilcNetListener listener;
+
+ listener =
+ silc_net_tcp_create_listener(&server_ip, 1, port, TRUE,
+ server->config->require_reverse_lookup,
+ server->schedule,
+ silc_server_accept_new_connection, server);
+ if (!listener) {
+ SILC_SERVER_LOG_ERROR(("Could not create server listener: %s on %hu",
+ server_ip, port));
+ return NULL;
}
- if (server->config->servers) {
- SilcServerConfigServer *ptr;
- SilcServerConfigServer *newptr;
- bool found;
+ return listener;
+}
- for (ptr = server->config->servers; ptr; ptr = ptr->next) {
- found = FALSE;
+/* Adds a secondary listener. */
- /* Check whether new config has this one too */
- for (newptr = newconfig->servers; newptr; newptr = newptr->next) {
- if (silc_string_compare(newptr->host, ptr->host)) {
- found = TRUE;
- break;
- }
- }
+SilcBool silc_server_init_secondary(SilcServer server)
+{
+#if 0
+ int sock = 0;
+ SilcPacketStream newsocket = NULL;
+ SilcServerConfigServerInfoInterface *interface;
- if (!found && ptr->host) {
- /* Remove this connection */
- SilcSocketConnection sock;
- sock = silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_SERVER,
- ptr->host, 0);
- if (sock && !SILC_IS_LISTENER(sock))
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rehash_close_connection,
- server, 0, 1, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- }
- }
- }
+ for (interface = server->config->server_info->secondary; interface;
+ interface = interface->next, sock++) {
- if (server->config->clients) {
- SilcServerConfigClient *ptr;
- SilcServerConfigClient *newptr;
- bool found;
+ if (!silc_server_listen(server,
+ interface->server_ip, interface->port, &sock_list[sock]))
+ goto err;
- for (ptr = server->config->clients; ptr; ptr = ptr->next) {
- found = FALSE;
+ /* Set socket to non-blocking mode */
+ silc_net_set_socket_nonblock(sock_list[sock]);
- /* Check whether new config has this one too */
- for (newptr = newconfig->clients; newptr; newptr = newptr->next) {
- if (silc_string_compare(newptr->host, ptr->host)) {
- found = TRUE;
- break;
- }
- }
+ /* Add ourselves also to the socket table. The entry allocated above
+ is sent as argument for fast referencing in the future. */
+ silc_socket_alloc(sock_list[sock],
+ SILC_CONN_SERVER, NULL, &newsocket);
+ server->sockets[sock_list[sock]] = newsocket;
+ SILC_SET_LISTENER(newsocket);
- if (!found && ptr->host) {
- /* Remove this connection */
- SilcSocketConnection sock;
- sock = silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_CLIENT,
- ptr->host, 0);
- if (sock)
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rehash_close_connection,
- server, 0, 1, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ /* Perform name and address lookups to resolve the listenning address
+ and port. */
+ if (!silc_net_check_local_by_sock(sock_list[sock], &newsocket->hostname,
+ &newsocket->ip)) {
+ if ((server->config->require_reverse_lookup && !newsocket->hostname) ||
+ !newsocket->ip) {
+ SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
+ newsocket->hostname ? newsocket->hostname :
+ newsocket->ip ? newsocket->ip : ""));
+ server->stat.conn_failures++;
+ goto err;
}
+ if (!newsocket->hostname)
+ newsocket->hostname = strdup(newsocket->ip);
}
+ newsocket->port = silc_net_get_local_port(sock);
+
+ newsocket->user_data = (void *)server->id_entry;
+ silc_schedule_task_add(server->schedule, sock_list[sock],
+ silc_server_accept_new_connection,
+ (void *)server, 0, 0,
+ SILC_TASK_FD,
+ SILC_TASK_PRI_NORMAL);
}
- /* Create connections after rehash */
- silc_server_create_connections(server);
+ return TRUE;
- /* Check whether our router status has changed */
- if (newconfig->servers) {
- SilcServerConfigServer *ptr = newconfig->servers;
+ err:
+ do silc_net_close_server(sock_list[sock--]); while (sock >= 0);
+#endif /* 0 */
+ return FALSE;
+}
- server->server_type = SILC_ROUTER;
- while (ptr) {
- if (ptr->backup_router) {
- server->server_type = SILC_BACKUP_ROUTER;
- server->backup_router = TRUE;
- server->id_entry->server_type = SILC_BACKUP_ROUTER;
- break;
- }
- ptr = ptr->next;
- }
- }
+/* Initializes the entire SILC server. This is called always before running
+ the server. This is called only once at the initialization of the program.
+ This binds the server to its listenning port. After this function returns
+ one should call silc_server_run to start the server. This returns TRUE
+ when everything is ok to run the server. Configuration file must be
+ read and parsed before calling this. */
- /* Our old config is gone now. We'll unreference our reference made in
- silc_server_init and then destroy it since we are destroying it
- underneath the application (layer which called silc_server_init). */
- silc_server_config_unref(&server->config_ref);
- silc_server_config_destroy(server->config);
+SilcBool silc_server_init(SilcServer server)
+{
+ SilcServerID *id;
+ SilcServerEntry id_entry;
+ SilcIDListPurge purge;
+ SilcNetListener listener;
+ SilcUInt16 *port;
+ char **ip;
- /* Take new config context */
- server->config = newconfig;
- silc_server_config_ref(&server->config_ref, server->config, server->config);
+ SILC_LOG_DEBUG(("Initializing server"));
+
+ server->starttime = time(NULL);
+
+ /* Take config object for us */
+ silc_server_config_ref(&server->config_ref, server->config,
+ server->config);
#ifdef SILC_DEBUG
/* Set debugging on if configured */
}
#endif /* SILC_DEBUG */
- SILC_LOG_DEBUG(("Server rehashed"));
+ /* Steal public and private key from the config object */
+ server->public_key = server->config->server_info->public_key;
+ server->private_key = server->config->server_info->private_key;
+ server->config->server_info->public_key = NULL;
+ server->config->server_info->private_key = NULL;
- return TRUE;
-}
+ /* Register all configured ciphers, PKCS and hash functions. */
+ if (!silc_server_config_register_ciphers(server))
+ silc_cipher_register_default();
+ if (!silc_server_config_register_pkcs(server))
+ silc_pkcs_register_default();
+ if (!silc_server_config_register_hashfuncs(server))
+ silc_hash_register_default();
+ if (!silc_server_config_register_hmacs(server))
+ silc_hmac_register_default();
-/* The heart of the server. This runs the scheduler thus runs the server.
- When this returns the server has been stopped and the program will
- be terminated. */
+ /* Initialize random number generator for the server. */
+ server->rng = silc_rng_alloc();
+ silc_rng_init(server->rng);
+ silc_rng_global_init(server->rng);
-void silc_server_run(SilcServer server)
-{
- SILC_LOG_INFO(("SILC Server started"));
+ /* Initialize hash functions for server to use */
+ silc_hash_alloc("md5", &server->md5hash);
+ silc_hash_alloc("sha1", &server->sha1hash);
- /* Start the scheduler, the heart of the SILC server. When this returns
- the program will be terminated. */
- silc_schedule(server->schedule);
-}
+ /* Initialize the scheduler */
+ server->schedule = silc_schedule_init(server->config->param.connections_max,
+ server);
+ if (!server->schedule)
+ goto err;
-/* Stops the SILC server. This function is used to shutdown the server.
- This is usually called after the scheduler has returned. After stopping
- the server one should call silc_server_free. */
+ /* First, register log files configuration for error output */
+ silc_server_config_setlogfiles(server);
-void silc_server_stop(SilcServer server)
-{
- SILC_LOG_INFO(("SILC Server shutting down"));
+ /* Initialize ID caches */
+ server->local_list->clients =
+ silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor,
+ server);
+ server->local_list->servers =
+ silc_idcache_alloc(0, SILC_ID_SERVER, NULL, NULL);
+ server->local_list->channels =
+ silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, NULL);
+
+ /* These are allocated for normal server as well as these hold some
+ global information that the server has fetched from its router. For
+ router these are used as they are supposed to be used on router. */
+ server->global_list->clients =
+ silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor,
+ server);
+ server->global_list->servers =
+ silc_idcache_alloc(0, SILC_ID_SERVER, NULL, NULL);
+ server->global_list->channels =
+ silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, NULL);
+
+ /* Init watcher lists */
+ server->watcher_list =
+ silc_hash_table_alloc(1, silc_hash_client_id_hash, NULL,
+ silc_hash_data_compare, (void *)CLIENTID_HASH_LEN,
+ NULL, NULL, TRUE);
+ if (!server->watcher_list)
+ goto err;
+ server->watcher_list_pk =
+ silc_hash_table_alloc(1, silc_hash_public_key, NULL,
+ silc_hash_public_key_compare, NULL,
+ NULL, NULL, TRUE);
+ if (!server->watcher_list_pk)
+ goto err;
+
+ /* Init public key list */
+ server->pk_hash =
+ silc_hash_table_alloc(0, silc_hash_public_key, NULL,
+ silc_hash_public_key_compare, NULL,
+ NULL, NULL, TRUE);
- if (server->schedule) {
- int i;
+ if (!server->pk_hash)
+ goto err;
- server->server_shutdown = TRUE;
+ /* Create TCP listener */
+ listener = silc_server_listen(
+ server,
+ server->config->server_info->primary == NULL ? NULL :
+ server->config->server_info->primary->server_ip,
+ server->config->server_info->primary == NULL ? 0 :
+ server->config->server_info->primary->port);
+ if (!listener)
+ goto err;
- /* Close all connections */
- for (i = 0; i < server->config->param.connections_max; i++) {
- if (!server->sockets[i])
- continue;
- if (!SILC_IS_LISTENER(server->sockets[i])) {
- SilcSocketConnection sock = server->sockets[i];
- SilcIDListData idata = sock->user_data;
-
- if (idata)
- idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
-
- silc_schedule_task_del_by_context(server->schedule,
- server->sockets[i]);
- silc_schedule_task_del_by_fd(server->schedule,
- server->sockets[i]->sock);
- silc_server_disconnect_remote(server, server->sockets[i],
- SILC_STATUS_OK,
- "Server is shutting down");
- if (server->sockets[i]) {
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock,
- "Server is shutting down");
- silc_socket_free(sock);
- }
- } else {
- silc_socket_free(server->sockets[i]);
- server->sockets[i] = NULL;
- server->stat.conn_num--;
- }
+ silc_dlist_add(server->listeners, listener);
+
+#if 0
+ /* Perform name and address lookups to resolve the listenning address
+ and port. */
+ if (!silc_net_check_local_by_sock(sock, &newsocket->hostname,
+ &newsocket->ip)) {
+ if ((server->config->require_reverse_lookup && !newsocket->hostname) ||
+ !newsocket->ip) {
+ SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
+ newsocket->hostname ? newsocket->hostname :
+ newsocket->ip ? newsocket->ip : ""));
+ server->stat.conn_failures++;
+ goto err;
}
+ if (!newsocket->hostname)
+ newsocket->hostname = strdup(newsocket->ip);
+ }
+ newsocket->port = silc_net_get_local_port(sock);
+#endif
- /* We are not connected to network anymore */
- server->standalone = TRUE;
+ /* Create a Server ID for the server. */
+ port = silc_net_listener_get_port(listener, NULL);
+ ip = silc_net_listener_get_ip(listener, NULL);
+ silc_id_create_server_id(ip[0], port[0], server->rng, &id);
+ if (!id)
+ goto err;
- silc_schedule_stop(server->schedule);
- silc_schedule_uninit(server->schedule);
- server->schedule = NULL;
+ silc_free(port);
+ silc_free(ip[0]);
+ silc_free(ip);
- silc_free(server->sockets);
- server->sockets = NULL;
+ server->id = id;
+ server->server_name = server->config->server_info->server_name;
+ server->config->server_info->server_name = NULL;
+
+ /* Add ourselves to the server list. We don't have a router yet
+ beacuse we haven't established a route yet. It will be done later.
+ For now, NULL is sent as router. This allocates new entry to
+ the ID list. */
+ id_entry =
+ silc_idlist_add_server(server->local_list, strdup(server->server_name),
+ server->server_type, server->id, NULL, NULL);
+ if (!id_entry) {
+ SILC_LOG_ERROR(("Could not add ourselves to cache"));
+ goto err;
}
+ id_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
+ server->id_entry = id_entry;
- silc_server_protocols_unregister();
+ /* Create secondary TCP listeners */
+ if (silc_server_init_secondary(server) == FALSE)
+ goto err;
- SILC_LOG_DEBUG(("Server stopped"));
-}
+ /* Create connections to configured routers. */
+ silc_server_create_connections(server);
-/* Function that is called when the network connection to a router has
- been established. This will continue with the key exchange protocol
- with the remote router. */
+ server->listenning = TRUE;
-void silc_server_start_key_exchange(SilcServer server,
- SilcServerConnection sconn,
- int sock)
-{
- SilcSocketConnection newsocket;
- SilcProtocol protocol;
- SilcServerKEInternalContext *proto_ctx;
- SilcServerConfigRouter *conn =
- (SilcServerConfigRouter *) sconn->conn.ref_ptr;
- void *context;
+ /* Allocate the entire socket list that is used in server. Eventually
+ all connections will have entry in this table (it is a table of
+ pointers to the actual object that is allocated individually
+ later). */
+ server->sockets = silc_calloc(server->config->param.connections_max,
+ sizeof(*server->sockets));
+ if (!server->sockets)
+ goto err;
- /* Cancel any possible retry timeouts */
- silc_schedule_task_del_by_callback(server->schedule,
- silc_server_connect_to_router_retry);
-
- /* Set socket options */
- silc_net_set_socket_nonblock(sock);
- silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
-
- /* Create socket connection for the connection. Even though we
- know that we are connecting to a router we will mark the socket
- to be unknown connection until we have executed authentication
- protocol. */
- silc_socket_alloc(sock, SILC_SOCKET_TYPE_UNKNOWN, NULL, &newsocket);
- server->sockets[sock] = newsocket;
- newsocket->hostname = strdup(sconn->remote_host);
- newsocket->ip = strdup(sconn->remote_host);
- newsocket->port = sconn->remote_port;
- sconn->sock = newsocket;
-
- /* Allocate internal protocol context. This is sent as context
- to the protocol. */
- proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
- proto_ctx->server = (void *)server;
- proto_ctx->context = (void *)sconn;
- proto_ctx->sock = newsocket;
- proto_ctx->rng = server->rng;
- proto_ctx->responder = FALSE;
+ /* If server connections has been configured then we must be router as
+ normal server cannot have server connections, only router connections. */
+ if (server->config->servers) {
+ SilcServerConfigServer *ptr = server->config->servers;
- /* Set Key Exchange flags from configuration, but fall back to global
- settings too. */
- SILC_GET_SKE_FLAGS(conn, proto_ctx);
- if (server->config->param.key_exchange_pfs)
- proto_ctx->flags |= SILC_SKE_SP_FLAG_PFS;
-
- /* Perform key exchange protocol. silc_server_connect_to_router_second
- will be called after the protocol is finished. */
- silc_protocol_alloc(SILC_PROTOCOL_SERVER_KEY_EXCHANGE,
- &protocol, proto_ctx,
- silc_server_connect_to_router_second);
- newsocket->protocol = protocol;
-
- /* Register a timeout task that will be executed if the protocol
- is not executed within set limit. */
- proto_ctx->timeout_task =
- silc_schedule_task_add(server->schedule, sock,
- silc_server_timeout_remote,
- server, server->config->key_exchange_timeout, 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_LOW);
-
- /* Register the connection for network input and output. This sets
- that scheduler will listen for incoming packets for this connection
- and sets that outgoing packets may be sent to this connection as
- well. However, this doesn't set the scheduler for outgoing traffic,
- it will be set separately by calling SILC_SET_CONNECTION_FOR_OUTPUT,
- later when outgoing data is available. */
- context = (void *)server;
- SILC_REGISTER_CONNECTION_FOR_IO(sock);
-
- /* Run the protocol */
- silc_protocol_execute(protocol, server->schedule, 0, 0);
-}
+ server->server_type = SILC_ROUTER;
+ while (ptr) {
+ if (ptr->backup_router) {
+ server->server_type = SILC_BACKUP_ROUTER;
+ server->backup_router = TRUE;
+ server->id_entry->server_type = SILC_BACKUP_ROUTER;
+ break;
+ }
+ ptr = ptr->next;
+ }
+ }
-/* Timeout callback that will be called to retry connecting to remote
- router. This is used by both normal and router server. This will wait
- before retrying the connecting. The timeout is generated by exponential
- backoff algorithm. */
+ /* Register the ID Cache purge task. This periodically purges the ID cache
+ and removes the expired cache entries. */
-SILC_TASK_CALLBACK(silc_server_connect_to_router_retry)
-{
- SilcServer server = app_context;
- SilcServerConnection sconn = (SilcServerConnection)context;
- SilcServerConfigRouter *conn = sconn->conn.ref_ptr;
- SilcServerConfigConnParams *param =
- (conn->param ? conn->param : &server->config->param);
+ /* Clients local list */
+ server->purge_i = purge = silc_calloc(1, sizeof(*purge));
+ purge->cache = server->local_list->clients;
+ purge->timeout = 600;
+ silc_schedule_task_add_timeout(server->schedule, silc_idlist_purge,
+ (void *)purge, purge->timeout, 0);
- /* Don't retry if we are shutting down. */
- if (server->server_shutdown) {
- silc_server_config_unref(&sconn->conn);
- silc_free(sconn->remote_host);
- silc_free(sconn->backup_replace_ip);
- silc_free(sconn);
- return;
- }
+ /* Clients global list */
+ server->purge_g = purge = silc_calloc(1, sizeof(*purge));
+ purge->cache = server->global_list->clients;
+ purge->timeout = 300;
+ silc_schedule_task_add_timeout(server->schedule, silc_idlist_purge,
+ (void *)purge, purge->timeout, 0);
- SILC_LOG_INFO(("Retrying connecting to a router"));
+ /* If we are normal server we'll retrieve network statisticial information
+ once in a while from the router. */
+ if (server->server_type != SILC_ROUTER)
+ silc_schedule_task_add_timeout(server->schedule, silc_server_get_stats,
+ server, 10, 0);
- /* Calculate next timeout */
- if (sconn->retry_count >= 1) {
- sconn->retry_timeout = sconn->retry_timeout * SILC_SERVER_RETRY_MULTIPLIER;
- if (sconn->retry_timeout > param->reconnect_interval_max)
- sconn->retry_timeout = param->reconnect_interval_max;
- } else {
- sconn->retry_timeout = param->reconnect_interval;
- }
- sconn->retry_count++;
- sconn->retry_timeout = sconn->retry_timeout +
- (silc_rng_get_rn32(server->rng) % SILC_SERVER_RETRY_RANDOMIZER);
+ if (server->server_type == SILC_ROUTER)
+ server->stat.routers++;
- /* If we've reached max retry count, give up. */
- if ((sconn->retry_count > param->reconnect_count) &&
- !param->reconnect_keep_trying) {
- SILC_LOG_ERROR(("Could not connect to router, giving up"));
- silc_server_config_unref(&sconn->conn);
- silc_free(sconn->remote_host);
- silc_free(sconn->backup_replace_ip);
- silc_free(sconn);
- return;
- }
+ /* Start packet engine */
+ server->packet_engine =
+ silc_packet_engine_start(server->rng, server->server_type == SILC_ROUTER,
+ &silc_server_stream_cbs, server);
+ if (!server->packet_engine)
+ goto err;
- SILC_LOG_DEBUG(("Retrying connecting to a router in %d seconds",
- sconn->retry_timeout));
+ SILC_LOG_DEBUG(("Server initialized"));
- /* We will lookup a fresh pointer later */
- silc_server_config_unref(&sconn->conn);
+ /* We are done here, return succesfully */
+ return TRUE;
- /* Wait one before retrying */
- silc_schedule_task_add(server->schedule, 0, silc_server_connect_router,
- context, sconn->retry_timeout, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ err:
+ silc_server_config_unref(&server->config_ref);
+ return FALSE;
}
-/* Callback for async connection to remote router */
+#if 0
+/* Task callback to close a socket connection after rehash */
-SILC_TASK_CALLBACK(silc_server_connection_established)
+SILC_TASK_CALLBACK(silc_server_rehash_close_connection)
{
- SilcServer server = app_context;
- SilcServerConnection sconn = (SilcServerConnection)context;
- int sock = fd;
- int opt = EINVAL, optlen = sizeof(opt), ret;
-
- ret = silc_net_get_socket_opt(sock, SOL_SOCKET, SO_ERROR, &opt, &optlen);
-
- silc_schedule_task_del_by_fd(server->schedule, sock);
- silc_schedule_unset_listen_fd(server->schedule, sock);
+ SilcServer server = context;
+ SilcPacketStream sock = server->sockets[fd];
- if (ret != 0 || opt != 0) {
- SILC_LOG_ERROR(("Could not connect to router %s:%d: %s",
- sconn->remote_host, sconn->remote_port, strerror(opt)));
- silc_net_close_connection(sock);
- if (!sconn->no_reconnect) {
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router_retry,
- context, 1, 0, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- } else {
- silc_server_config_unref(&sconn->conn);
- silc_free(sconn->remote_host);
- silc_free(sconn->backup_replace_ip);
- silc_free(sconn);
- }
+ if (!sock)
return;
- }
-
- SILC_LOG_DEBUG(("Connection to router %s:%d established", sconn->remote_host,
- sconn->remote_port));
- /* Continue with key exchange protocol */
- silc_server_start_key_exchange(server, sconn, sock);
+ SILC_LOG_INFO(("Connection %s:%d [%s] is unconfigured",
+ sock->hostname, sock->port,
+ (sock->type == SILC_CONN_UNKNOWN ? "Unknown" :
+ sock->type == SILC_CONN_CLIENT ? "Client" :
+ sock->type == SILC_CONN_SERVER ? "Server" :
+ "Router")));
+ silc_schedule_task_del_by_context(server->schedule, sock);
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_BANNED_FROM_SERVER,
+ "This connection is removed from "
+ "configuration");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
}
+#endif /* 0 */
-/* Generic routine to use connect to a router. */
+/* This function basically reads the config file again and switches the config
+ object pointed by the server object. After that, we have to fix various
+ things such as the server_name and the listening ports.
+ Keep in mind that we no longer have the root privileges at this point. */
-SILC_TASK_CALLBACK(silc_server_connect_router)
+SilcBool silc_server_rehash(SilcServer server)
{
- SilcServer server = app_context;
- SilcServerConnection sconn = (SilcServerConnection)context;
- SilcServerConfigRouter *rconn;
- int sock;
+#if 0
+ SilcServerConfig newconfig;
- /* Don't connect if we are shutting down. */
- if (server->server_shutdown) {
- silc_free(sconn->remote_host);
- silc_free(sconn->backup_replace_ip);
- silc_free(sconn);
- return;
- }
+ SILC_LOG_INFO(("Rehashing server"));
- SILC_LOG_INFO(("Connecting to the %s %s on port %d",
- (sconn->backup ? "backup router" : "router"),
- sconn->remote_host, sconn->remote_port));
+ /* Reset the logging system */
+ silc_log_quick(TRUE);
+ silc_log_flush_all();
- server->router_connect = time(NULL);
- rconn = silc_server_config_find_router_conn(server, sconn->remote_host,
- sconn->remote_port);
- if (!rconn) {
- SILC_LOG_INFO(("Unconfigured %s connection %s:%d, cannot connect",
- (sconn->backup ? "backup router" : "router"),
- sconn->remote_host, sconn->remote_port));
- silc_free(sconn->remote_host);
- silc_free(sconn->backup_replace_ip);
- silc_free(sconn);
- return;
+ /* Start the main rehash phase (read again the config file) */
+ newconfig = silc_server_config_alloc(server->config_file, server);
+ if (!newconfig) {
+ SILC_LOG_ERROR(("Rehash FAILED."));
+ return FALSE;
}
- silc_server_config_ref(&sconn->conn, server->config, (void *)rconn);
- /* Connect to remote host */
- sock = silc_net_create_connection_async(
- (!server->config->server_info->primary ? NULL :
- server->config->server_info->primary->server_ip),
- sconn->remote_port, sconn->remote_host);
- if (sock < 0) {
- SILC_LOG_ERROR(("Could not connect to router %s:%d",
- sconn->remote_host, sconn->remote_port));
- if (!sconn->no_reconnect) {
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router_retry,
- context, 1, 0, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- } else {
- silc_server_config_unref(&sconn->conn);
- silc_free(sconn->remote_host);
- silc_free(sconn->backup_replace_ip);
- silc_free(sconn);
- }
- return;
- }
+ /* Reinit scheduler if necessary */
+ if (newconfig->param.connections_max > server->config->param.connections_max)
+ if (!silc_schedule_reinit(server->schedule,
+ newconfig->param.connections_max))
+ return FALSE;
- /* wait for the connection to be established */
- silc_schedule_task_add(server->schedule, sock,
- silc_server_connection_established,
- context, 0, 0, SILC_TASK_FD,
- SILC_TASK_PRI_NORMAL);
- silc_schedule_set_listen_fd(server->schedule, sock,
- SILC_TASK_WRITE, FALSE);
-}
+ /* Fix the server_name field */
+ if (strcmp(server->server_name, newconfig->server_info->server_name)) {
+ silc_free(server->server_name);
-/* This function connects to our primary router or if we are a router this
- establishes all our primary routes. This is called at the start of the
- server to do authentication and key exchange with our router - called
- from schedule. */
+ /* Check server name */
+ server->server_name =
+ silc_identifier_check(newconfig->server_info->server_name,
+ strlen(newconfig->server_info->server_name),
+ SILC_STRING_LOCALE, 256, NULL);
+ if (!server->server_name) {
+ SILC_LOG_ERROR(("Malformed server name string '%s'",
+ server->config->server_info->server_name));
+ return FALSE;
+ }
-SILC_TASK_CALLBACK_GLOBAL(silc_server_connect_to_router)
-{
- SilcServer server = (SilcServer)context;
- SilcServerConnection sconn;
- SilcServerConfigRouter *ptr;
+ /* Update the idcache list with a fresh pointer */
+ silc_free(server->id_entry->server_name);
+ server->id_entry->server_name = strdup(server->server_name);
+ if (!silc_idcache_del_by_context(server->local_list->servers,
+ server->id_entry))
+ return FALSE;
+ if (!silc_idcache_add(server->local_list->servers,
+ strdup(server->id_entry->server_name),
+ server->id_entry->id, server->id_entry, 0, NULL))
+ return FALSE;
+ }
- /* Don't connect if we are shutting down. */
- if (server->server_shutdown)
- return;
+ /* Set logging */
+ silc_server_config_setlogfiles(server);
- SILC_LOG_DEBUG(("We are %s",
- (server->server_type == SILC_SERVER ?
- "normal server" : server->server_type == SILC_ROUTER ?
- "router" : "backup router/normal server")));
+ /* Change new key pair if necessary */
+ if (newconfig->server_info->public_key &&
+ !silc_pkcs_public_key_compare(server->public_key,
+ newconfig->server_info->public_key)) {
+ silc_pkcs_public_key_free(server->public_key);
+ silc_pkcs_private_key_free(server->private_key);
+ server->public_key = newconfig->server_info->public_key;
+ server->private_key = newconfig->server_info->private_key;
+ newconfig->server_info->public_key = NULL;
+ newconfig->server_info->private_key = NULL;
- if (!server->config->routers) {
- /* There wasn't a configured router, we will continue but we don't
- have a connection to outside world. We will be standalone server. */
- SILC_LOG_DEBUG(("No router(s), we are standalone"));
- server->standalone = TRUE;
- return;
+ /* Allocate PKCS context for local public and private keys */
+ silc_pkcs_free(server->pkcs);
+ if (!silc_pkcs_alloc(server->public_key->name, &server->pkcs))
+ return FALSE;
+ silc_pkcs_public_key_set(server->pkcs, server->public_key);
+ silc_pkcs_private_key_set(server->pkcs, server->private_key);
}
- /* Cancel any possible retry timeouts */
- silc_schedule_task_del_by_callback(server->schedule,
- silc_server_connect_router);
- silc_schedule_task_del_by_callback(server->schedule,
- silc_server_connect_to_router_retry);
-
- /* Create the connections to all our routes */
- for (ptr = server->config->routers; ptr; ptr = ptr->next) {
+ /* Check for unconfigured server and router connections and close
+ connections that were unconfigured. */
- SILC_LOG_DEBUG(("%s connection [%s] %s:%d",
- ptr->backup_router ? "Backup router" : "Router",
- ptr->initiator ? "Initiator" : "Responder",
- ptr->host, ptr->port));
+ if (server->config->routers) {
+ SilcServerConfigRouter *ptr;
+ SilcServerConfigRouter *newptr;
+ SilcBool found;
- if (server->server_type == SILC_ROUTER && ptr->backup_router &&
- ptr->initiator == FALSE && !server->backup_router &&
- !silc_server_config_get_backup_router(server))
- server->wait_backup = TRUE;
+ for (ptr = server->config->routers; ptr; ptr = ptr->next) {
+ found = FALSE;
- if (ptr->initiator) {
- /* Check whether we are connecting or connected to this host already */
- if (silc_server_num_sockets_by_remote(server,
- silc_net_is_ip(ptr->host) ?
- ptr->host : NULL,
- silc_net_is_ip(ptr->host) ?
- NULL : ptr->host, ptr->port,
- SILC_SOCKET_TYPE_ROUTER)) {
- SILC_LOG_DEBUG(("We are already connected to this router"));
-
- /* If we don't have primary router and this connection is our
- primary router we are in desync. Reconnect to the primary. */
- if (server->standalone && !server->router) {
- SilcServerConfigRouter *primary =
- silc_server_config_get_primary_router(server);
- if (primary == ptr) {
- SilcSocketConnection sock =
- silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_ROUTER,
- ptr->host, ptr->port);
- if (sock) {
- server->backup_noswitch = TRUE;
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- silc_server_disconnect_remote(server, sock, 0, NULL);
- server->backup_noswitch = FALSE;
- SILC_LOG_DEBUG(("Reconnecting to primary router"));
- } else {
- continue;
- }
- } else {
- continue;
- }
- } else {
- continue;
+ /* Check whether new config has this one too */
+ for (newptr = newconfig->routers; newptr; newptr = newptr->next) {
+ if (silc_string_compare(newptr->host, ptr->host) &&
+ newptr->port == ptr->port &&
+ newptr->initiator == ptr->initiator) {
+ found = TRUE;
+ break;
}
}
- if (silc_server_num_sockets_by_remote(server,
- silc_net_is_ip(ptr->host) ?
- ptr->host : NULL,
- silc_net_is_ip(ptr->host) ?
- NULL : ptr->host, ptr->port,
- SILC_SOCKET_TYPE_UNKNOWN)) {
- SILC_LOG_DEBUG(("We are already connecting to this router"));
- continue;
- }
- /* Allocate connection object for hold connection specific stuff. */
- sconn = silc_calloc(1, sizeof(*sconn));
- sconn->remote_host = strdup(ptr->host);
- sconn->remote_port = ptr->port;
- sconn->backup = ptr->backup_router;
- if (sconn->backup) {
- sconn->backup_replace_ip = strdup(ptr->backup_replace_ip);
- sconn->backup_replace_port = ptr->backup_replace_port;
+ if (!found && ptr->host) {
+ /* Remove this connection */
+ SilcPacketStream sock;
+ sock = silc_server_find_socket_by_host(server, SILC_CONN_ROUTER,
+ ptr->host, ptr->port);
+ if (sock && !SILC_IS_LISTENER(sock))
+ silc_schedule_task_add(server->schedule, sock->sock,
+ silc_server_rehash_close_connection,
+ server, 0, 1, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
}
-
- if (!server->router_conn && !sconn->backup)
- server->router_conn = sconn;
-
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_router,
- (void *)sconn, 0, 1, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
}
}
-}
-/* Second part of connecting to router(s). Key exchange protocol has been
- executed and now we will execute authentication protocol. */
-
-SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
-{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerKEInternalContext *ctx =
- (SilcServerKEInternalContext *)protocol->context;
- SilcServer server = (SilcServer)ctx->server;
- SilcServerConnection sconn = (SilcServerConnection)ctx->context;
- SilcSocketConnection sock = ctx->sock;
- SilcServerConnAuthInternalContext *proto_ctx;
- SilcServerConfigRouter *conn = NULL;
+ if (server->config->servers) {
+ SilcServerConfigServer *ptr;
+ SilcServerConfigServer *newptr;
+ SilcBool found;
- SILC_LOG_DEBUG(("Start"));
+ for (ptr = server->config->servers; ptr; ptr = ptr->next) {
+ found = FALSE;
- if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
- protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
- /* Error occured during protocol */
- silc_protocol_free(protocol);
- sock->protocol = NULL;
- silc_ske_free_key_material(ctx->keymat);
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- if (ctx->ske)
- silc_ske_free(ctx->ske);
- silc_free(ctx->dest_id);
- silc_free(ctx);
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+ /* Check whether new config has this one too */
+ for (newptr = newconfig->servers; newptr; newptr = newptr->next) {
+ if (silc_string_compare(newptr->host, ptr->host)) {
+ found = TRUE;
+ break;
+ }
+ }
- /* Try reconnecting if configuration wants it */
- if (!sconn->no_reconnect) {
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router_retry,
- sconn, 1, 0, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- return;
+ if (!found && ptr->host) {
+ /* Remove this connection */
+ SilcPacketStream sock;
+ sock = silc_server_find_socket_by_host(server, SILC_CONN_SERVER,
+ ptr->host, 0);
+ if (sock && !SILC_IS_LISTENER(sock))
+ silc_schedule_task_add(server->schedule, sock->sock,
+ silc_server_rehash_close_connection,
+ server, 0, 1, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+ }
}
-
- /* Call completion to indicate error */
- if (sconn->callback)
- (*sconn->callback)(server, NULL, sconn->callback_context);
-
- silc_server_config_unref(&sconn->conn);
- silc_free(sconn->remote_host);
- silc_free(sconn->backup_replace_ip);
- silc_free(sconn);
- return;
}
- /* We now have the key material as the result of the key exchange
- protocol. Take the key material into use. Free the raw key material
- as soon as we've set them into use. */
- if (!silc_server_protocol_ke_set_keys(server, ctx->ske,
- ctx->sock, ctx->keymat,
- ctx->ske->prop->cipher,
- ctx->ske->prop->pkcs,
- ctx->ske->prop->hash,
- ctx->ske->prop->hmac,
- ctx->ske->prop->group,
- ctx->responder)) {
- silc_protocol_free(protocol);
- sock->protocol = NULL;
- silc_ske_free_key_material(ctx->keymat);
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- if (ctx->ske)
- silc_ske_free(ctx->ske);
- silc_free(ctx->dest_id);
- silc_free(ctx);
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
-
- /* Try reconnecting if configuration wants it */
- if (!sconn->no_reconnect) {
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router_retry,
- sconn, 1, 0, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- return;
- }
+ if (server->config->clients) {
+ SilcServerConfigClient *ptr;
+ SilcServerConfigClient *newptr;
+ SilcBool found;
- /* Call completion to indicate error */
- if (sconn->callback)
- (*sconn->callback)(server, NULL, sconn->callback_context);
+ for (ptr = server->config->clients; ptr; ptr = ptr->next) {
+ found = FALSE;
- silc_server_config_unref(&sconn->conn);
- silc_free(sconn->remote_host);
- silc_free(sconn->backup_replace_ip);
- silc_free(sconn);
- return;
- }
- silc_ske_free_key_material(ctx->keymat);
-
- /* Allocate internal context for the authentication protocol. This
- is sent as context for the protocol. */
- proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
- proto_ctx->server = (void *)server;
- proto_ctx->context = (void *)sconn;
- proto_ctx->sock = sock;
- proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
- proto_ctx->dest_id_type = ctx->dest_id_type;
- proto_ctx->dest_id = ctx->dest_id;
-
- /* Resolve the authentication method used in this connection. Check if
- we find a match from user configured connections */
- if (!sconn->conn.ref_ptr)
- conn = silc_server_config_find_router_conn(server, sock->hostname,
- sock->port);
- else
- conn = sconn->conn.ref_ptr;
+ /* Check whether new config has this one too */
+ for (newptr = newconfig->clients; newptr; newptr = newptr->next) {
+ if (silc_string_compare(newptr->host, ptr->host)) {
+ found = TRUE;
+ break;
+ }
+ }
- if (conn) {
- /* Match found. Use the configured authentication method. Take only
- the passphrase, since for public key auth we automatically use
- our local key pair. */
- if (conn->passphrase) {
- if (conn->publickeys && !server->config->prefer_passphrase_auth) {
- proto_ctx->auth_meth = SILC_AUTH_PUBLIC_KEY;
- } else {
- proto_ctx->auth_data = strdup(conn->passphrase);
- proto_ctx->auth_data_len = strlen(conn->passphrase);
- proto_ctx->auth_meth = SILC_AUTH_PASSWORD;
+ if (!found && ptr->host) {
+ /* Remove this connection */
+ SilcPacketStream sock;
+ sock = silc_server_find_socket_by_host(server, SILC_CONN_CLIENT,
+ ptr->host, 0);
+ if (sock)
+ silc_schedule_task_add(server->schedule, sock->sock,
+ silc_server_rehash_close_connection,
+ server, 0, 1, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
}
- } else if (conn->publickeys) {
- proto_ctx->auth_meth = SILC_AUTH_PUBLIC_KEY;
- } else {
- proto_ctx->auth_meth = SILC_AUTH_NONE;
}
- } else {
- SILC_LOG_ERROR(("Could not find connection data for %s (%s) on port",
- sock->hostname, sock->ip, sock->port));
- silc_protocol_free(protocol);
- sock->protocol = NULL;
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- if (ctx->ske)
- silc_ske_free(ctx->ske);
- silc_free(ctx->dest_id);
- silc_free(ctx);
- silc_server_config_unref(&sconn->conn);
- silc_free(sconn->remote_host);
- silc_free(sconn->backup_replace_ip);
- silc_free(sconn);
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
- return;
}
- /* Free old protocol as it is finished now */
- silc_protocol_free(protocol);
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- silc_free(ctx);
- sock->protocol = NULL;
-
- /* Allocate the authentication protocol. This is allocated here
- but we won't start it yet. We will be receiving party of this
- protocol thus we will wait that connecting party will make
- their first move. */
- silc_protocol_alloc(SILC_PROTOCOL_SERVER_CONNECTION_AUTH,
- &sock->protocol, proto_ctx,
- silc_server_connect_to_router_final);
-
- /* Register timeout task. If the protocol is not executed inside
- this timelimit the connection will be terminated. */
- proto_ctx->timeout_task =
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_timeout_remote,
- (void *)server,
- server->config->conn_auth_timeout, 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_LOW);
-
- /* Run the protocol */
- silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
-}
-
-/* Finalizes the connection to router. Registers a server task to the
- queue so that we can accept new connections. */
-
-SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
-{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerConnAuthInternalContext *ctx =
- (SilcServerConnAuthInternalContext *)protocol->context;
- SilcServer server = (SilcServer)ctx->server;
- SilcServerConnection sconn = (SilcServerConnection)ctx->context;
- SilcSocketConnection sock = ctx->sock;
- SilcServerEntry id_entry = NULL;
- SilcBuffer packet;
- unsigned char *id_string;
- SilcUInt32 id_len;
- SilcIDListData idata;
- SilcServerConfigRouter *conn = NULL;
- SilcServerConfigConnParams *param = NULL;
-
- SILC_LOG_DEBUG(("Start"));
+ /* Create connections after rehash */
+ silc_server_create_connections(server);
- if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
- protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
- /* Error occured during protocol */
- silc_free(ctx->dest_id);
- sock->protocol = NULL;
- silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_AUTH_FAILED,
- NULL);
- sock->protocol = protocol;
+ /* Check whether our router status has changed */
+ if (newconfig->servers) {
+ SilcServerConfigServer *ptr = newconfig->servers;
- /* Try reconnecting if configuration wants it */
- if (!sconn->no_reconnect) {
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router_retry,
- sconn, 1, 0, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- goto out2;
+ server->server_type = SILC_ROUTER;
+ while (ptr) {
+ if (ptr->backup_router) {
+ server->server_type = SILC_BACKUP_ROUTER;
+ server->backup_router = TRUE;
+ server->id_entry->server_type = SILC_BACKUP_ROUTER;
+ break;
+ }
+ ptr = ptr->next;
}
-
- goto out;
}
- /* Add a task to the queue. This task receives new connections to the
- server. This task remains on the queue until the end of the program. */
- if (!server->listenning && !sconn->backup) {
- silc_schedule_task_add(server->schedule, server->sock,
- silc_server_accept_new_connection,
- (void *)server, 0, 0,
- SILC_TASK_FD,
- SILC_TASK_PRI_NORMAL);
- server->listenning = TRUE;
- }
-
- /* Send NEW_SERVER packet to the router. We will become registered
- to the SILC network after sending this packet. */
- id_string = silc_id_id2str(server->id, SILC_ID_SERVER);
- id_len = silc_id_get_len(server->id, SILC_ID_SERVER);
- packet = silc_buffer_alloc(2 + 2 + id_len + strlen(server->server_name));
- silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
- silc_buffer_format(packet,
- SILC_STR_UI_SHORT(id_len),
- SILC_STR_UI_XNSTRING(id_string, id_len),
- SILC_STR_UI_SHORT(strlen(server->server_name)),
- SILC_STR_UI_XNSTRING(server->server_name,
- strlen(server->server_name)),
- SILC_STR_END);
-
- /* Send the packet */
- silc_server_packet_send(server, ctx->sock, SILC_PACKET_NEW_SERVER, 0,
- packet->data, packet->len, TRUE);
- silc_buffer_free(packet);
- silc_free(id_string);
-
- SILC_LOG_INFO(("Connected to router %s", sock->hostname));
-
- /* Check that we do not have this ID already */
- id_entry = silc_idlist_find_server_by_id(server->local_list,
- ctx->dest_id, TRUE, NULL);
- if (id_entry) {
- silc_idcache_del_by_context(server->local_list->servers, id_entry);
- } else {
- id_entry = silc_idlist_find_server_by_id(server->global_list,
- ctx->dest_id, TRUE, NULL);
- if (id_entry)
- silc_idcache_del_by_context(server->global_list->servers, id_entry);
- }
+ /* Our old config is gone now. We'll unreference our reference made in
+ silc_server_init and then destroy it since we are destroying it
+ underneath the application (layer which called silc_server_init). */
+ silc_server_config_unref(&server->config_ref);
+ silc_server_config_destroy(server->config);
- SILC_LOG_DEBUG(("New server id(%s)",
- silc_id_render(ctx->dest_id, SILC_ID_SERVER)));
+ /* Take new config context */
+ server->config = newconfig;
+ silc_server_config_ref(&server->config_ref, server->config, server->config);
- /* Add the connected router to global server list. Router is sent
- as NULL since it's local to us. */
- id_entry = silc_idlist_add_server(server->global_list,
- strdup(sock->hostname),
- SILC_ROUTER, ctx->dest_id, NULL, sock);
- if (!id_entry) {
- silc_free(ctx->dest_id);
- SILC_LOG_ERROR(("Cannot add new server entry to cache"));
- sock->protocol = NULL;
- silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_AUTH_FAILED,
- NULL);
- sock->protocol = protocol;
- goto out;
+#ifdef SILC_DEBUG
+ /* Set debugging on if configured */
+ if (server->config->debug_string) {
+ silc_log_debug(TRUE);
+ silc_log_set_debug_string(server->config->debug_string);
}
+#endif /* SILC_DEBUG */
- silc_idlist_add_data(id_entry, (SilcIDListData)sock->user_data);
- silc_free(sock->user_data);
- sock->user_data = (void *)id_entry;
- sock->type = SILC_SOCKET_TYPE_ROUTER;
- idata = (SilcIDListData)sock->user_data;
- idata->status |= (SILC_IDLIST_STATUS_REGISTERED |
- SILC_IDLIST_STATUS_LOCAL);
-
- conn = sconn->conn.ref_ptr;
- param = &server->config->param;
- if (conn && conn->param)
- param = conn->param;
-
- /* Perform keepalive. */
- silc_socket_set_heartbeat(sock, param->keepalive_secs, server,
- silc_server_perform_heartbeat,
- server->schedule);
-
- /* Register re-key timeout */
- idata->rekey->timeout = param->key_exchange_rekey;
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rekey_callback,
- (void *)sock, idata->rekey->timeout, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-
- if (!sconn->backup) {
- /* Mark this router our primary router if we're still standalone */
- if (server->standalone) {
- SILC_LOG_DEBUG(("This connection is our primary router"));
- server->id_entry->router = id_entry;
- server->router = id_entry;
- server->router->server_type = SILC_ROUTER;
- server->standalone = FALSE;
- server->backup_primary = FALSE;
-
- /* Announce data if we are not backup router (unless not as primary
- currently). Backup router announces later at the end of
- resuming protocol. */
- if (server->backup_router && server->server_type == SILC_ROUTER) {
- SILC_LOG_DEBUG(("Announce data after resume protocol"));
- } else {
- /* If we are router then announce our possible servers. Backup
- router announces also global servers. */
- if (server->server_type == SILC_ROUTER)
- silc_server_announce_servers(server,
- server->backup_router ? TRUE : FALSE,
- 0, SILC_PRIMARY_ROUTE(server));
-
- /* Announce our clients and channels to the router */
- silc_server_announce_clients(server, 0, SILC_PRIMARY_ROUTE(server));
- silc_server_announce_channels(server, 0, SILC_PRIMARY_ROUTE(server));
- }
-
- /* If we are backup router then this primary router is whom we are
- backing up. */
- if (server->server_type == SILC_BACKUP_ROUTER)
- silc_server_backup_add(server, server->id_entry, sock->ip,
- sconn->remote_port, TRUE);
- }
- } else {
- /* Add this server to be our backup router */
- id_entry->server_type = SILC_BACKUP_ROUTER;
- silc_server_backup_add(server, id_entry, sconn->backup_replace_ip,
- sconn->backup_replace_port, FALSE);
- }
+ SILC_LOG_DEBUG(("Server rehashed"));
+#endif /* 0 */
- sock->protocol = NULL;
+ return TRUE;
+}
- out:
- /* Call the completion callback to indicate that we've connected to
- the router */
- if (sconn && sconn->callback)
- (*sconn->callback)(server, id_entry, sconn->callback_context);
+/* The heart of the server. This runs the scheduler thus runs the server.
+ When this returns the server has been stopped and the program will
+ be terminated. */
- /* Free the temporary connection data context */
- if (sconn) {
- silc_server_config_unref(&sconn->conn);
- silc_free(sconn->remote_host);
- silc_free(sconn->backup_replace_ip);
- silc_free(sconn);
- }
- if (sconn == server->router_conn)
- server->router_conn = NULL;
+void silc_server_run(SilcServer server)
+{
+ SILC_LOG_INFO(("SILC Server started"));
- out2:
- /* Free the protocol object */
- if (sock->protocol == protocol)
- sock->protocol = NULL;
- silc_protocol_free(protocol);
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- if (ctx->ske)
- silc_ske_free(ctx->ske);
- if (ctx->auth_meth == SILC_AUTH_PASSWORD)
- silc_free(ctx->auth_data);
- silc_free(ctx);
+ /* Start the scheduler, the heart of the SILC server. When this returns
+ the program will be terminated. */
+ silc_schedule(server->schedule);
}
-/* Host lookup callback that is called after the incoming connection's
- IP and FQDN lookup is performed. This will actually check the acceptance
- of the incoming connection and will register the key exchange protocol
- for this connection. */
-
-static void
-silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
- void *context)
+/* Stops the SILC server. This function is used to shutdown the server.
+ This is usually called after the scheduler has returned. After stopping
+ the server one should call silc_server_free. */
+
+void silc_server_stop(SilcServer server)
{
- SilcServerKEInternalContext *proto_ctx =
- (SilcServerKEInternalContext *)context;
- SilcServer server = (SilcServer)proto_ctx->server;
- SilcServerConfigClient *cconfig = NULL;
- SilcServerConfigServer *sconfig = NULL;
- SilcServerConfigRouter *rconfig = NULL;
- SilcServerConfigDeny *deny;
- int port;
-
- /* Check whether we could resolve both IP and FQDN. */
- if (!sock->ip || (!strcmp(sock->ip, sock->hostname) &&
- server->config->require_reverse_lookup)) {
- SILC_LOG_ERROR(("IP/DNS lookup failed %s",
- sock->hostname ? sock->hostname :
- sock->ip ? sock->ip : ""));
- server->stat.conn_failures++;
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
- "Unknown host or IP");
- silc_free(proto_ctx);
- return;
- }
+ SilcDList list;
+ SilcPacketStream ps;
- /* Register the connection for network input and output. This sets
- that scheduler will listen for incoming packets for this connection
- and sets that outgoing packets may be sent to this connection as well.
- However, this doesn't set the scheduler for outgoing traffic, it
- will be set separately by calling SILC_SET_CONNECTION_FOR_OUTPUT,
- later when outgoing data is available. */
- context = (void *)server;
- SILC_REGISTER_CONNECTION_FOR_IO(sock->sock);
+ SILC_LOG_INFO(("SILC Server shutting down"));
- SILC_LOG_INFO(("Incoming connection %s (%s)", sock->hostname,
- sock->ip));
+ server->server_shutdown = TRUE;
- /* Listenning port */
- if (!server->sockets[SILC_PTR_TO_32(proto_ctx->context)]) {
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_RESOURCE_LIMIT,
- "Connection refused");
- server->stat.conn_failures++;
- silc_free(proto_ctx);
- return;
- }
- port = server->sockets[SILC_PTR_TO_32(proto_ctx->context)]->port;
+ /* Close all connections */
+ if (server->packet_engine) {
+ list = silc_packet_engine_get_streams(server->packet_engine);
- /* Check whether this connection is denied to connect to us. */
- deny = silc_server_config_find_denied(server, sock->ip);
- if (!deny)
- deny = silc_server_config_find_denied(server, sock->hostname);
- if (deny) {
- /* The connection is denied */
- SILC_LOG_INFO(("Connection %s (%s) is denied",
- sock->hostname, sock->ip));
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_BANNED_FROM_SERVER,
- deny->reason);
- server->stat.conn_failures++;
- silc_free(proto_ctx);
- return;
- }
+ silc_dlist_start(list);
+ while ((ps = silc_dlist_get(list))) {
+ SilcIDListData idata = silc_packet_get_context(ps);
- /* Check whether we have configured this sort of connection at all. We
- have to check all configurations since we don't know what type of
- connection this is. */
- if (!(cconfig = silc_server_config_find_client(server, sock->ip)))
- cconfig = silc_server_config_find_client(server, sock->hostname);
- if (!(sconfig = silc_server_config_find_server_conn(server, sock->ip)))
- sconfig = silc_server_config_find_server_conn(server, sock->hostname);
- if (server->server_type == SILC_ROUTER) {
- if (!(rconfig = silc_server_config_find_router_conn(server,
- sock->ip, sock->port)))
- rconfig = silc_server_config_find_router_conn(server, sock->hostname,
- sock->port);
- }
- if (!cconfig && !sconfig && !rconfig) {
- SILC_LOG_INFO(("Connection %s (%s) is not allowed", sock->hostname,
- sock->ip));
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_BANNED_FROM_SERVER, NULL);
- server->stat.conn_failures++;
- silc_free(proto_ctx);
- return;
- }
+ if (idata)
+ idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
- /* The connection is allowed */
+ silc_server_disconnect_remote(server, ps, SILC_STATUS_OK,
+ "Server is shutting down");
+ silc_server_free_sock_user_data(server, ps,
+ "Server is shutting down");
+ }
+ }
- /* Set internal context for key exchange protocol. This is
- sent as context for the protocol. */
- proto_ctx->sock = sock;
- proto_ctx->rng = server->rng;
- proto_ctx->responder = TRUE;
- silc_server_config_ref(&proto_ctx->cconfig, server->config, cconfig);
- silc_server_config_ref(&proto_ctx->sconfig, server->config, sconfig);
- silc_server_config_ref(&proto_ctx->rconfig, server->config, rconfig);
+ /* We are not connected to network anymore */
+ server->standalone = TRUE;
- /* Take flags for key exchange. Since we do not know what type of connection
- this is, we go through all found configurations and use the global ones
- as well. This will result always into strictest key exchange flags. */
- SILC_GET_SKE_FLAGS(cconfig, proto_ctx);
- SILC_GET_SKE_FLAGS(sconfig, proto_ctx);
- SILC_GET_SKE_FLAGS(rconfig, proto_ctx);
- if (server->config->param.key_exchange_pfs)
- proto_ctx->flags |= SILC_SKE_SP_FLAG_PFS;
+ silc_schedule_stop(server->schedule);
+ silc_schedule_uninit(server->schedule);
+ server->schedule = NULL;
- /* Prepare the connection for key exchange protocol. We allocate the
- protocol but will not start it yet. The connector will be the
- initiator of the protocol thus we will wait for initiation from
- there before we start the protocol. */
- server->stat.auth_attempts++;
- SILC_LOG_DEBUG(("Starting key exchange protocol"));
- silc_protocol_alloc(SILC_PROTOCOL_SERVER_KEY_EXCHANGE,
- &sock->protocol, proto_ctx,
- silc_server_accept_new_connection_second);
-
- /* Register a timeout task that will be executed if the connector
- will not start the key exchange protocol within specified timeout
- and the connection will be closed. */
- proto_ctx->timeout_task =
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_timeout_remote,
- (void *)server,
- server->config->key_exchange_timeout, 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_LOW);
+ SILC_LOG_DEBUG(("Server stopped"));
}
-/* Accepts new connections to the server. Accepting new connections are
- done in three parts to make it async. */
+#if 0
+/* Parses whole packet, received earlier. */
-SILC_TASK_CALLBACK(silc_server_accept_new_connection)
+SILC_TASK_CALLBACK(silc_server_packet_parse_real)
{
- SilcServer server = (SilcServer)context;
- SilcSocketConnection newsocket;
- SilcServerKEInternalContext *proto_ctx;
- int sock;
+ SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
+ SilcServer server = (SilcServer)parse_ctx->context;
+ SilcPacketStream sock = parse_ctx->sock;
+ SilcPacket *packet = parse_ctx->packet;
+ SilcIDListData idata = (SilcIDListData)sock->user_data;
+ int ret;
- SILC_LOG_DEBUG(("Accepting new connection"));
+ if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
+ SILC_LOG_DEBUG(("Connection is disconnected"));
+ goto out;
+ }
- server->stat.conn_attempts++;
+ server->stat.packets_received++;
- sock = silc_net_accept_connection(fd);
- if (sock < 0) {
- SILC_LOG_ERROR(("Could not accept new connection: %s", strerror(errno)));
- server->stat.conn_failures++;
- return;
+ /* Parse the packet */
+ if (parse_ctx->normal)
+ ret = silc_packet_parse(packet, idata ? idata->receive_key : NULL);
+ else
+ ret = silc_packet_parse_special(packet, idata ? idata->receive_key : NULL);
+
+ /* If entry is disabled ignore what we got. */
+ if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED &&
+ ret != SILC_PACKET_HEARTBEAT && ret != SILC_PACKET_RESUME_ROUTER &&
+ ret != SILC_PACKET_REKEY && ret != SILC_PACKET_REKEY_DONE &&
+ ret != SILC_PACKET_KEY_EXCHANGE_1 && ret != SILC_PACKET_KEY_EXCHANGE_2) {
+ SILC_LOG_DEBUG(("Connection is disabled (packet %s dropped)",
+ silc_get_packet_name(ret)));
+ goto out;
}
- /* Check for maximum allowed connections */
- if (sock > server->config->param.connections_max) {
- SILC_LOG_ERROR(("Refusing connection, server is full"));
- server->stat.conn_failures++;
- silc_net_close_connection(sock);
- return;
+ if (ret == SILC_PACKET_NONE) {
+ SILC_LOG_DEBUG(("Error parsing packet"));
+ goto out;
}
- server->stat.conn_num++;
- /* Set socket options */
- silc_net_set_socket_nonblock(sock);
- silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
-
- /* We don't create a ID yet, since we don't know what type of connection
- this is yet. But, we do add the connection to the socket table. */
- silc_socket_alloc(sock, SILC_SOCKET_TYPE_UNKNOWN, NULL, &newsocket);
- server->sockets[sock] = newsocket;
-
- /* Perform asynchronous host lookup. This will lookup the IP and the
- FQDN of the remote connection. After the lookup is done the connection
- is accepted further. */
- proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
- proto_ctx->server = server;
- proto_ctx->context = SILC_32_TO_PTR(fd);
- silc_socket_host_lookup(newsocket, TRUE,
- silc_server_accept_new_connection_lookup,
- (void *)proto_ctx, server->schedule);
-}
+ /* Check that the the current client ID is same as in the client's packet. */
+ if (sock->type == SILC_CONN_CLIENT) {
+ SilcClientEntry client = (SilcClientEntry)sock->user_data;
+ if (client && client->id && packet->src_id) {
+ void *id = silc_id_str2id(packet->src_id, packet->src_id_len,
+ packet->src_id_type);
+ if (!id || !SILC_ID_CLIENT_COMPARE(client->id, id)) {
+ silc_free(id);
+ SILC_LOG_DEBUG(("Packet source is not same as sender"));
+ goto out;
+ }
+ silc_free(id);
+ }
+ }
-/* Second part of accepting new connection. Key exchange protocol has been
- performed and now it is time to do little connection authentication
- protocol to figure out whether this connection is client or server
- and whether it has right to access this server (especially server
- connections needs to be authenticated). */
+ if (server->server_type == SILC_ROUTER) {
+ /* Route the packet if it is not destined to us. Other ID types but
+ server are handled separately after processing them. */
+ if (packet->dst_id && !(packet->flags & SILC_PACKET_FLAG_BROADCAST) &&
+ packet->dst_id_type == SILC_ID_SERVER &&
+ sock->type != SILC_CONN_CLIENT &&
+ memcmp(packet->dst_id, server->id_string, server->id_string_len)) {
+ SilcPacketStream conn;
-SILC_TASK_CALLBACK(silc_server_accept_new_connection_second)
-{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerKEInternalContext *ctx =
- (SilcServerKEInternalContext *)protocol->context;
- SilcServer server = (SilcServer)ctx->server;
- SilcSocketConnection sock = ctx->sock;
- SilcServerConnAuthInternalContext *proto_ctx;
+ /* Route the packet to fastest route for the destination ID */
+ void *id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type);
+ if (!id)
+ goto out;
- SILC_LOG_DEBUG(("Start"));
+ conn = silc_server_route_get(server, id, packet->dst_id_type);
+ if (!conn) {
+ SILC_LOG_WARNING(("Packet to unknown server ID %s, dropped (no route)",
+ silc_id_render(id, SILC_ID_SERVER)));
+ goto out;
+ }
- if ((protocol->state == SILC_PROTOCOL_STATE_ERROR) ||
- (protocol->state == SILC_PROTOCOL_STATE_FAILURE)) {
- /* Error occured during protocol */
- SILC_LOG_DEBUG(("Error in key exchange protocol"));
- silc_protocol_free(protocol);
- sock->protocol = NULL;
- silc_ske_free_key_material(ctx->keymat);
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- if (ctx->ske)
- silc_ske_free(ctx->ske);
- silc_free(ctx->dest_id);
- silc_server_config_unref(&ctx->cconfig);
- silc_server_config_unref(&ctx->sconfig);
- silc_server_config_unref(&ctx->rconfig);
- silc_free(ctx);
-
- if (!SILC_IS_DISCONNECTING(sock)) {
- SILC_LOG_INFO(("Key exchange failed for %s:%d [%s]", sock->hostname,
- sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_KEY_EXCHANGE_FAILED,
- NULL);
+ silc_server_packet_route(server, conn, packet);
+ silc_free(id);
+ goto out;
}
-
- server->stat.auth_failures++;
- return;
}
- /* We now have the key material as the result of the key exchange
- protocol. Take the key material into use. Free the raw key material
- as soon as we've set them into use. */
- if (!silc_server_protocol_ke_set_keys(server, ctx->ske,
- ctx->sock, ctx->keymat,
- ctx->ske->prop->cipher,
- ctx->ske->prop->pkcs,
- ctx->ske->prop->hash,
- ctx->ske->prop->hmac,
- ctx->ske->prop->group,
- ctx->responder)) {
- SILC_LOG_ERROR(("Error setting key material in use"));
- silc_protocol_free(protocol);
- sock->protocol = NULL;
- silc_ske_free_key_material(ctx->keymat);
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- if (ctx->ske)
- silc_ske_free(ctx->ske);
- silc_free(ctx->dest_id);
- silc_server_config_unref(&ctx->cconfig);
- silc_server_config_unref(&ctx->sconfig);
- silc_server_config_unref(&ctx->rconfig);
- silc_free(ctx);
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
- server->stat.auth_failures++;
- return;
+ /* Parse the incoming packet type */
+ silc_server_packet_parse_type(server, sock, packet);
+
+ /* Broadcast packet if it is marked as broadcast packet and it is
+ originated from router and we are router. */
+ if (server->server_type == SILC_ROUTER &&
+ sock->type == SILC_CONN_ROUTER &&
+ packet->flags & SILC_PACKET_FLAG_BROADCAST) {
+ /* Broadcast to our primary route */
+ silc_server_packet_broadcast(server, SILC_PRIMARY_ROUTE(server), packet);
+
+ /* If we have backup routers then we need to feed all broadcast
+ data to those servers. */
+ silc_server_backup_broadcast(server, sock, packet);
}
- silc_ske_free_key_material(ctx->keymat);
-
- /* Allocate internal context for the authentication protocol. This
- is sent as context for the protocol. */
- proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
- proto_ctx->server = (void *)server;
- proto_ctx->sock = sock;
- proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
- proto_ctx->responder = TRUE;
- proto_ctx->dest_id_type = ctx->dest_id_type;
- proto_ctx->dest_id = ctx->dest_id;
- proto_ctx->cconfig = ctx->cconfig;
- proto_ctx->sconfig = ctx->sconfig;
- proto_ctx->rconfig = ctx->rconfig;
-
- /* Free old protocol as it is finished now */
- silc_protocol_free(protocol);
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- silc_free(ctx);
- sock->protocol = NULL;
-
- /* Allocate the authentication protocol. This is allocated here
- but we won't start it yet. We will be receiving party of this
- protocol thus we will wait that connecting party will make
- their first move. */
- SILC_LOG_DEBUG(("Starting connection authentication protocol"));
- silc_protocol_alloc(SILC_PROTOCOL_SERVER_CONNECTION_AUTH,
- &sock->protocol, proto_ctx,
- silc_server_accept_new_connection_final);
-
- /* Register timeout task. If the protocol is not executed inside
- this timelimit the connection will be terminated. */
- proto_ctx->timeout_task =
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_timeout_remote,
- (void *)server,
- server->config->conn_auth_timeout, 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_LOW);
+
+ out:
+ silc_packet_context_free(packet);
+ silc_free(parse_ctx);
}
+#endif /* 0 */
-/* After this is called, server don't wait for backup router anymore.
- This gets called automatically even after we have backup router
- connection established. */
-SILC_TASK_CALLBACK(silc_server_backup_router_wait)
+/******************************* Connecting *********************************/
+
+/* Free connection context */
+
+static void silc_server_connection_free(SilcServerConnection sconn)
{
- SilcServer server = context;
- server->wait_backup = FALSE;
+ silc_dlist_del(sconn->server->conns, sconn);
+ silc_server_config_unref(&sconn->conn);
+ silc_free(sconn->remote_host);
+ silc_free(sconn->backup_replace_ip);
+ silc_free(sconn);
}
-/* Final part of accepting new connection. The connection has now
- been authenticated and keys has been exchanged. We also know whether
- this is client or server connection. */
+/* Creates connection to a remote router. */
-SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
+void silc_server_create_connection(SilcServer server,
+ SilcBool reconnect,
+ const char *remote_host, SilcUInt32 port,
+ SilcServerConnectCallback callback,
+ void *context)
{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerConnAuthInternalContext *ctx =
- (SilcServerConnAuthInternalContext *)protocol->context;
- SilcServer server = (SilcServer)ctx->server;
- SilcSocketConnection sock = ctx->sock;
- SilcUnknownEntry entry = (SilcUnknownEntry)sock->user_data;
- void *id_entry;
- SilcServerConfigConnParams *param = &server->config->param;
+ SilcServerConnection sconn;
- if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
- protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
- /* Error occured during protocol */
- SILC_LOG_DEBUG(("Error during authentication protocol"));
- silc_protocol_free(protocol);
- sock->protocol = NULL;
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- if (ctx->ske)
- silc_ske_free(ctx->ske);
- silc_free(ctx->dest_id);
- silc_server_config_unref(&ctx->cconfig);
- silc_server_config_unref(&ctx->sconfig);
- silc_server_config_unref(&ctx->rconfig);
- silc_free(ctx);
-
- if (!SILC_IS_DISCONNECTING(sock)) {
- SILC_LOG_INFO(("Authentication failed for %s:%d [%s]", sock->hostname,
- sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
- silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_AUTH_FAILED,
- NULL);
- }
- server->stat.auth_failures++;
+ /* Allocate connection object for hold connection specific stuff. */
+ sconn = silc_calloc(1, sizeof(*sconn));
+ if (!sconn)
return;
- }
-
- entry->data.last_receive = time(NULL);
+ sconn->remote_host = strdup(remote_host);
+ sconn->remote_port = port;
+ sconn->no_reconnect = reconnect == FALSE;
+ sconn->callback = callback;
+ sconn->callback_context = context;
- switch (ctx->conn_type) {
- case SILC_SOCKET_TYPE_CLIENT:
- {
- SilcClientEntry client;
- SilcServerConfigClient *conn = ctx->cconfig.ref_ptr;
+ silc_schedule_task_add_timeout(server->schedule, silc_server_connect_router,
+ sconn, 0, 0);
+}
- /* Verify whether this connection is after all allowed to connect */
- if (!silc_server_connection_allowed(server, sock, ctx->conn_type,
- &server->config->param,
- conn->param, ctx->ske)) {
- server->stat.auth_failures++;
- goto out;
- }
+/* Connection authentication completion callback */
- /* If we are primary router and we have backup router configured
- but it has not connected to use yet, do not accept any other
- connection. */
- if (server->wait_backup && server->server_type == SILC_ROUTER &&
- !server->backup_router) {
- SilcServerConfigRouter *router;
- router = silc_server_config_get_backup_router(server);
- if (router && strcmp(server->config->server_info->primary->server_ip,
- sock->ip) &&
- silc_server_find_socket_by_host(server,
- SILC_SOCKET_TYPE_SERVER,
- router->backup_replace_ip, 0)) {
- SILC_LOG_INFO(("Will not accept connections because we do "
- "not have backup router connection established"));
- sock->protocol = NULL;
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_PERM_DENIED,
- "We do not have connection to backup "
- "router established, try later");
- silc_free(sock->user_data);
- server->stat.auth_failures++;
+static void
+silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
+ void *context)
+{
+ SilcServerConnection sconn = context;
+ SilcUnknownEntry entry = silc_packet_get_context(sconn->sock);
+ SilcServer server = entry->server;
+ SilcServerConfigServer *conn;
+ SilcServerConfigConnParams *param;
+ SilcIDListData idata;
+ SilcServerEntry id_entry;
+ unsigned char id[32];
+ SilcUInt32 id_len;
+ SilcID remote_id;
- /* From here on, wait 20 seconds for the backup router to appear. */
- silc_schedule_task_add(server->schedule, 0,
- silc_server_backup_router_wait,
- (void *)server, 20, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
- goto out;
- }
- }
+ SILC_LOG_DEBUG(("Connection authentication completed"));
- SILC_LOG_DEBUG(("Remote host is client"));
- SILC_LOG_INFO(("Connection %s (%s) is client", sock->hostname,
- sock->ip));
+ if (success == FALSE) {
+ /* Authentication failed */
+ /* XXX retry connecting */
- /* Add the client to the client ID cache. The nickname and Client ID
- and other information is created after we have received NEW_CLIENT
- packet from client. */
- client = silc_idlist_add_client(server->local_list,
- NULL, NULL, NULL, NULL, NULL, sock, 0);
- if (!client) {
- SILC_LOG_ERROR(("Could not add new client to cache"));
- silc_free(sock->user_data);
- sock->protocol = NULL;
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_AUTH_FAILED, NULL);
- server->stat.auth_failures++;
- goto out;
- }
- entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
+ silc_server_disconnect_remote(server, sconn->sock,
+ SILC_STATUS_ERR_AUTH_FAILED, NULL);
+ return;
+ }
- /* Statistics */
- server->stat.my_clients++;
- server->stat.clients++;
- server->stat.cell_clients++;
+ SILC_LOG_INFO(("Connected to %s %s",
+ SILC_CONNTYPE_STRING(entry->data.conn_type),
+ sconn->remote_host));
+
+ /* Create the actual entry for remote entity */
+ switch (entry->data.conn_type) {
+ case SILC_CONN_SERVER:
+ SILC_LOG_DEBUG(("Remote is SILC server"));
+
+ /* Add new server. The server must register itself to us before it
+ becomes registered to SILC network. */
+ id_entry = silc_idlist_add_server(server->local_list,
+ strdup(sconn->remote_host),
+ SILC_SERVER, NULL, NULL, sconn->sock);
+ if (!id_entry) {
+ silc_server_disconnect_remote(server, sconn->sock,
+ SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ silc_server_connection_free(sconn);
+ silc_free(entry);
+ return;
+ }
- /* Get connection parameters */
- if (conn->param) {
- param = conn->param;
+ silc_idlist_add_data(id_entry, (SilcIDListData)entry);
+ break;
- if (!param->keepalive_secs)
- param->keepalive_secs = server->config->param.keepalive_secs;
+ case SILC_CONN_ROUTER:
+ SILC_LOG_DEBUG(("Remote is SILC router"));
- if (!param->qos && server->config->param.qos) {
- param->qos = server->config->param.qos;
- param->qos_rate_limit = server->config->param.qos_rate_limit;
- param->qos_bytes_limit = server->config->param.qos_bytes_limit;
- param->qos_limit_sec = server->config->param.qos_limit_sec;
- param->qos_limit_usec = server->config->param.qos_limit_usec;
- }
+ /* Register to network */
+ silc_id_id2str(server->id, SILC_ID_SERVER, id, sizeof(id), &id_len);
+ if (!silc_packet_send_va(sconn->sock, SILC_PACKET_NEW_SERVER, 0,
+ SILC_STR_UI_SHORT(id_len),
+ SILC_STR_DATA(id, id_len),
+ SILC_STR_UI_SHORT(strlen(server->server_name)),
+ SILC_STR_DATA(server->server_name,
+ strlen(server->server_name)),
+ SILC_STR_END)) {
+ silc_server_disconnect_remote(server, sconn->sock,
+ SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ silc_server_connection_free(sconn);
+ silc_free(entry);
+ return;
+ }
- /* Check if to be anonymous connection */
- if (param->anonymous)
- client->mode |= SILC_UMODE_ANONYMOUS;
- }
+ /* Get remote ID */
+ silc_packet_get_ids(sconn->sock, NULL, NULL, NULL, &remote_id);
- /* Add public key to hash list (for whois using attributes) */
- if (!silc_hash_table_find_by_context(server->pk_hash,
- entry->data.public_key,
- client, NULL))
- silc_hash_table_add(server->pk_hash,
- entry->data.public_key, client);
+ /* Check that we do not have this ID already */
+ id_entry = silc_idlist_find_server_by_id(server->local_list,
+ &remote_id.u.server_id,
+ TRUE, NULL);
+ if (id_entry) {
+ silc_idcache_del_by_context(server->local_list->servers, id_entry, NULL);
+ } else {
+ id_entry = silc_idlist_find_server_by_id(server->global_list,
+ &remote_id.u.server_id,
+ TRUE, NULL);
+ if (id_entry)
+ silc_idcache_del_by_context(server->global_list->servers, id_entry,
+ NULL);
+ }
- id_entry = (void *)client;
- break;
+ SILC_LOG_DEBUG(("New server id(%s)",
+ silc_id_render(&remote_id.u.server_id, SILC_ID_SERVER)));
+
+ /* Add the connected router to global server list. Router is sent
+ as NULL since it's local to us. */
+ id_entry = silc_idlist_add_server(server->global_list,
+ strdup(sconn->remote_host),
+ SILC_ROUTER, &remote_id.u.server_id,
+ NULL, sconn->sock);
+ if (!id_entry) {
+ silc_server_disconnect_remote(server, sconn->sock,
+ SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ silc_server_connection_free(sconn);
+ silc_free(entry);
+ return;
}
- case SILC_SOCKET_TYPE_SERVER:
- case SILC_SOCKET_TYPE_ROUTER:
- {
- SilcServerEntry new_server;
- bool initiator = FALSE;
- bool backup_local = FALSE;
- bool backup_router = FALSE;
- char *backup_replace_ip = NULL;
- SilcUInt16 backup_replace_port = 0;
- SilcServerConfigServer *sconn = ctx->sconfig.ref_ptr;
- SilcServerConfigRouter *rconn = ctx->rconfig.ref_ptr;
- /* If we are backup router and this is incoming server connection
- and we do not have connection to primary router, do not allow
- the connection. */
- if (server->server_type == SILC_BACKUP_ROUTER &&
- ctx->conn_type == SILC_SOCKET_TYPE_SERVER &&
- !SILC_PRIMARY_ROUTE(server)) {
- SILC_LOG_INFO(("Will not accept server connection because we do "
- "not have primary router connection established"));
- sock->protocol = NULL;
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_PERM_DENIED,
- "We do not have connection to primary "
- "router established, try later");
- silc_free(sock->user_data);
- server->stat.auth_failures++;
- goto out;
- }
+ /* Registered */
+ silc_idlist_add_data(id_entry, (SilcIDListData)entry);
+ idata = (SilcIDListData)entry;
+ idata->status |= (SILC_IDLIST_STATUS_REGISTERED |
+ SILC_IDLIST_STATUS_LOCAL);
+
+ if (!sconn->backup) {
+ /* Mark this router our primary router if we're still standalone */
+ if (server->standalone) {
+ SILC_LOG_DEBUG(("This connection is our primary router"));
+ server->id_entry->router = id_entry;
+ server->router = id_entry;
+ server->router->server_type = SILC_ROUTER;
+ server->standalone = FALSE;
+ server->backup_primary = FALSE;
- if (ctx->conn_type == SILC_SOCKET_TYPE_ROUTER) {
- /* Verify whether this connection is after all allowed to connect */
- if (!silc_server_connection_allowed(server, sock, ctx->conn_type,
- &server->config->param,
- rconn ? rconn->param : NULL,
- ctx->ske)) {
- silc_free(sock->user_data);
- server->stat.auth_failures++;
- goto out;
+ /* Announce data if we are not backup router (unless not as primary
+ currently). Backup router announces later at the end of
+ resuming protocol. */
+ if (server->backup_router && server->server_type == SILC_ROUTER) {
+ SILC_LOG_DEBUG(("Announce data after resume protocol"));
+ } else {
+ /* If we are router then announce our possible servers. Backup
+ router announces also global servers. */
+ if (server->server_type == SILC_ROUTER)
+ silc_server_announce_servers(server,
+ server->backup_router ? TRUE : FALSE,
+ 0, SILC_PRIMARY_ROUTE(server));
+
+ /* Announce our clients and channels to the router */
+ silc_server_announce_clients(server, 0, SILC_PRIMARY_ROUTE(server));
+ silc_server_announce_channels(server, 0, SILC_PRIMARY_ROUTE(server));
}
- if (rconn) {
- if (rconn->param) {
- param = rconn->param;
+#if 0
+ /* If we are backup router then this primary router is whom we are
+ backing up. */
+ if (server->server_type == SILC_BACKUP_ROUTER)
+ silc_server_backup_add(server, server->id_entry, sock->ip,
+ sconn->remote_port, TRUE);
+#endif /* 0 */
+ }
+ } else {
+ /* Add this server to be our backup router */
+ id_entry->server_type = SILC_BACKUP_ROUTER;
+ silc_server_backup_add(server, id_entry, sconn->backup_replace_ip,
+ sconn->backup_replace_port, FALSE);
+ }
- if (!param->keepalive_secs)
- param->keepalive_secs = server->config->param.keepalive_secs;
+ break;
- if (!param->qos && server->config->param.qos) {
- param->qos = server->config->param.qos;
- param->qos_rate_limit = server->config->param.qos_rate_limit;
- param->qos_bytes_limit = server->config->param.qos_bytes_limit;
- param->qos_limit_sec = server->config->param.qos_limit_sec;
- param->qos_limit_usec = server->config->param.qos_limit_usec;
- }
- }
+ default:
+ silc_server_disconnect_remote(server, sconn->sock,
+ SILC_STATUS_ERR_AUTH_FAILED, NULL);
+ silc_server_connection_free(sconn);
+ silc_free(entry);
+ return;
+ }
- initiator = rconn->initiator;
- backup_local = rconn->backup_local;
- backup_router = rconn->backup_router;
- backup_replace_ip = rconn->backup_replace_ip;
- backup_replace_port = rconn->backup_replace_port;
- }
- }
+ conn = sconn->conn.ref_ptr;
+ param = &server->config->param;
+ if (conn && conn->param)
+ param = conn->param;
- if (ctx->conn_type == SILC_SOCKET_TYPE_SERVER) {
- /* Verify whether this connection is after all allowed to connect */
- if (!silc_server_connection_allowed(server, sock, ctx->conn_type,
- &server->config->param,
- sconn ? sconn->param : NULL,
- ctx->ske)) {
- silc_free(sock->user_data);
- server->stat.auth_failures++;
- goto out;
- }
- if (sconn) {
- if (sconn->param) {
- param = sconn->param;
+ /* Register rekey timeout */
+ sconn->rekey_timeout = param->key_exchange_rekey;
+ silc_schedule_task_add_timeout(server->schedule, silc_server_do_rekey,
+ sconn->sock, sconn->rekey_timeout, 0);
- if (!param->keepalive_secs)
- param->keepalive_secs = server->config->param.keepalive_secs;
+#if 0
+ /* Perform keepalive. */
+ silc_socket_set_heartbeat(sock, param->keepalive_secs, server,
+ silc_server_perform_heartbeat,
+ server->schedule);
- if (!param->qos && server->config->param.qos) {
- param->qos = server->config->param.qos;
- param->qos_rate_limit = server->config->param.qos_rate_limit;
- param->qos_bytes_limit = server->config->param.qos_bytes_limit;
- param->qos_limit_sec = server->config->param.qos_limit_sec;
- param->qos_limit_usec = server->config->param.qos_limit_usec;
- }
- }
+ out:
+ /* Call the completion callback to indicate that we've connected to
+ the router */
+ if (sconn && sconn->callback)
+ (*sconn->callback)(server, id_entry, sconn->callback_context);
- backup_router = sconn->backup_router;
- }
- }
+ /* Free the temporary connection data context */
+ if (sconn) {
+ silc_server_config_unref(&sconn->conn);
+ silc_free(sconn->remote_host);
+ silc_free(sconn->backup_replace_ip);
+ silc_free(sconn);
+ }
+ if (sconn == server->router_conn)
+ server->router_conn = NULL;
+#endif /* 0 */
- /* If we are primary router and we have backup router configured
- but it has not connected to use yet, do not accept any other
- connection. */
- if (server->wait_backup && server->server_type == SILC_ROUTER &&
- !server->backup_router && !backup_router) {
- SilcServerConfigRouter *router;
- router = silc_server_config_get_backup_router(server);
- if (router && strcmp(server->config->server_info->primary->server_ip,
- sock->ip) &&
- silc_server_find_socket_by_host(server,
- SILC_SOCKET_TYPE_SERVER,
- router->backup_replace_ip, 0)) {
- SILC_LOG_INFO(("Will not accept connections because we do "
- "not have backup router connection established"));
- sock->protocol = NULL;
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_PERM_DENIED,
- "We do not have connection to backup "
- "router established, try later");
- silc_free(sock->user_data);
- server->stat.auth_failures++;
+ silc_free(entry);
+}
- /* From here on, wait 20 seconds for the backup router to appear. */
- silc_schedule_task_add(server->schedule, 0,
- silc_server_backup_router_wait,
- (void *)server, 20, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
- goto out;
- }
- }
+/* SKE completion callback */
- SILC_LOG_DEBUG(("Remote host is %s",
- ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
- "server" : (backup_router ?
- "backup router" : "router")));
- SILC_LOG_INFO(("Connection %s (%s) is %s", sock->hostname,
- sock->ip, ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
- "server" : (backup_router ?
- "backup router" : "router")));
+static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
+ SilcSKESecurityProperties prop,
+ SilcSKEKeyMaterial keymat,
+ SilcSKERekeyMaterial rekey,
+ void *context)
+{
+ SilcServerConnection sconn = context;
+ SilcUnknownEntry entry = silc_packet_get_context(sconn->sock);
+ SilcServer server = entry->server;
+ SilcServerConfigRouter *conn = sconn->conn.ref_ptr;
+ SilcAuthMethod auth_meth = SILC_AUTH_NONE;
+ void *auth_data = NULL;
+ SilcUInt32 auth_data_len = 0;
+ SilcConnAuth connauth;
+ SilcCipher send_key, receive_key;
+ SilcHmac hmac_send, hmac_receive;
+ SilcHash hash;
+
+ if (status != SILC_SKE_STATUS_OK) {
+ /* SKE failed */
+ SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
+ silc_ske_map_status(status), entry->hostname, entry->ip));
+
+ /* XXX retry connecting */
+ silc_ske_free(ske);
+ silc_server_disconnect_remote(server, sconn->sock,
+ SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+ silc_server_connection_free(sconn);
+ return;
+ }
- /* Add the server into server cache. The server name and Server ID
- is updated after we have received NEW_SERVER packet from the
- server. We mark ourselves as router for this server if we really
- are router. */
- new_server =
- silc_idlist_add_server((ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
- server->local_list : (backup_router ?
- server->local_list :
- server->global_list)),
- NULL,
- (ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
- SILC_SERVER : SILC_ROUTER),
- NULL,
- (ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
- server->id_entry : (backup_router ?
- server->id_entry : NULL)),
- sock);
- if (!new_server) {
- SILC_LOG_ERROR(("Could not add new server to cache"));
- silc_free(sock->user_data);
- sock->protocol = NULL;
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_AUTH_FAILED, NULL);
- server->stat.auth_failures++;
- goto out;
- }
- entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
+ SILC_LOG_DEBUG(("Setting keys into use"));
- id_entry = (void *)new_server;
+ /* Set the keys into use. The data will be encrypted after this. */
+ if (!silc_ske_set_keys(ske, keymat, prop, &send_key, &receive_key,
+ &hmac_send, &hmac_receive, &hash)) {
- /* If the incoming connection is router and marked as backup router
- then add it to be one of our backups */
- if (ctx->conn_type == SILC_SOCKET_TYPE_ROUTER && backup_router) {
- /* Change it back to SERVER type since that's what it really is. */
- if (backup_local)
- ctx->conn_type = SILC_SOCKET_TYPE_SERVER;
- new_server->server_type = SILC_BACKUP_ROUTER;
+ /* XXX retry connecting */
- SILC_SERVER_SEND_OPERS(server, FALSE, TRUE, SILC_NOTIFY_TYPE_NONE,
- ("Backup router %s is now online",
- sock->hostname));
+ /* Error setting keys */
+ silc_ske_free(ske);
+ silc_server_disconnect_remote(server, sconn->sock,
+ SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+ silc_server_connection_free(sconn);
+ return;
+ }
+ silc_packet_set_keys(sconn->sock, send_key, receive_key, hmac_send,
+ hmac_receive, FALSE);
- /* Remove the backup waiting with timeout */
- silc_schedule_task_add(server->schedule, 0,
- silc_server_backup_router_wait,
- (void *)server, 10, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
- }
+ SILC_LOG_DEBUG(("Starting connection authentication"));
- /* Statistics */
- if (ctx->conn_type == SILC_SOCKET_TYPE_SERVER) {
- server->stat.my_servers++;
- server->stat.servers++;
+ connauth = silc_connauth_alloc(server->schedule, ske,
+ server->config->conn_auth_timeout);
+ if (!connauth) {
+ /* XXX retry connecting */
+
+ /** Error allocating auth protocol */
+ silc_ske_free(ske);
+ silc_server_disconnect_remote(server, sconn->sock,
+ SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ silc_server_connection_free(sconn);
+ return;
+ }
+
+ /* Get authentication method */
+ if (conn) {
+ if (conn->passphrase) {
+ if (conn->publickeys && !server->config->prefer_passphrase_auth) {
+ auth_meth = SILC_AUTH_PUBLIC_KEY;
+ auth_data = server->private_key;
} else {
- server->stat.my_routers++;
- server->stat.routers++;
+ auth_meth = SILC_AUTH_PASSWORD;
+ auth_data = conn->passphrase;
+ auth_data_len = conn->passphrase_len;
}
+ } else {
+ auth_meth = SILC_AUTH_PUBLIC_KEY;
+ auth_data = server->private_key;
+ }
+ }
- /* Check whether this connection is to be our primary router connection
- if we do not already have the primary route. */
- if (!backup_router &&
- server->standalone && ctx->conn_type == SILC_SOCKET_TYPE_ROUTER) {
- if (silc_server_config_is_primary_route(server) && !initiator)
- break;
+ /* Start connection authentication */
+ silc_connauth_initiator(connauth, server->server_type == SILC_ROUTER ?
+ SILC_CONN_ROUTER : SILC_CONN_SERVER, auth_meth,
+ auth_data, auth_data_len,
+ silc_server_ke_auth_compl, sconn);
+}
- SILC_LOG_DEBUG(("We are not standalone server anymore"));
- server->standalone = FALSE;
- if (!server->id_entry->router) {
- server->id_entry->router = id_entry;
- server->router = id_entry;
- }
- }
+/* Function that is called when the network connection to a router has
+ been established. This will continue with the key exchange protocol
+ with the remote router. */
- break;
- }
- default:
- goto out;
- break;
+void silc_server_start_key_exchange(SilcServerConnection sconn)
+{
+ SilcServer server = sconn->server;
+ SilcServerConfigRouter *conn = sconn->conn.ref_ptr;
+ SilcUnknownEntry entry;
+ SilcSKEParamsStruct params;
+ SilcSKE ske;
+
+ /* Cancel any possible retry timeouts */
+ silc_schedule_task_del_by_context(server->schedule, sconn);
+
+ /* Create packet stream */
+ sconn->sock = silc_packet_stream_create(server->packet_engine,
+ server->schedule, sconn->stream);
+ if (!sconn->sock) {
+ SILC_LOG_ERROR(("Cannot connect: cannot create packet stream"));
+ silc_stream_destroy(sconn->stream);
+ silc_server_connection_free(sconn);
+ return;
}
+ server->stat.conn_num++;
- sock->type = ctx->conn_type;
+ /* Set source ID to packet stream */
+ if (!silc_packet_set_ids(sconn->sock, SILC_ID_SERVER, &server->id,
+ 0, NULL)) {
+ silc_packet_stream_destroy(sconn->sock);
+ silc_server_connection_free(sconn);
+ return;
+ }
- /* Add the common data structure to the ID entry. */
- silc_idlist_add_data(id_entry, (SilcIDListData)sock->user_data);
+ /* Create entry for remote entity */
+ entry = silc_calloc(1, sizeof(*entry));
+ if (!entry) {
+ silc_packet_stream_destroy(sconn->sock);
+ silc_server_connection_free(sconn);
+ return;
+ }
+ entry->server = server;
+ silc_packet_set_context(sconn->sock, entry);
- /* Add to sockets internal pointer for fast referencing */
- silc_free(sock->user_data);
- sock->user_data = id_entry;
+ /* Set Key Exchange flags from configuration, but fall back to global
+ settings too. */
+ memset(¶ms, 0, sizeof(params));
+ SILC_GET_SKE_FLAGS(conn, params.flags);
+ if (server->config->param.key_exchange_pfs)
+ params.flags |= SILC_SKE_SP_FLAG_PFS;
- /* Connection has been fully established now. Everything is ok. */
- SILC_LOG_DEBUG(("New connection authenticated"));
+ /* Start SILC Key Exchange protocol */
+ SILC_LOG_DEBUG(("Starting key exchange protocol"));
+ ske = silc_ske_alloc(server->rng, server->schedule, server->repository,
+ server->public_key, server->private_key, sconn->sock);
+ if (!ske) {
+ silc_free(entry);
+ silc_packet_stream_destroy(sconn->sock);
+ silc_server_connection_free(sconn);
+ return;
+ }
+ silc_ske_set_callbacks(ske, silc_server_verify_key,
+ silc_server_ke_completed, sconn->sock);
+
+ /* Start key exchange protocol */
+ params.version = silc_version_string;
+ params.timeout_secs = server->config->key_exchange_timeout;
+ silc_ske_initiator(ske, sconn->sock, ¶ms, NULL);
+}
+
+/* Timeout callback that will be called to retry connecting to remote
+ router. This is used by both normal and router server. This will wait
+ before retrying the connecting. The timeout is generated by exponential
+ backoff algorithm. */
+
+SILC_TASK_CALLBACK(silc_server_connect_to_router_retry)
+{
+ SilcServerConnection sconn = context;
+ SilcServer server = sconn->server;
+ SilcServerConfigRouter *conn = sconn->conn.ref_ptr;
+ SilcServerConfigConnParams *param =
+ (conn->param ? conn->param : &server->config->param);
+
+ SILC_LOG_INFO(("Retrying connecting to %s:%d", sconn->remote_host,
+ sconn->remote_port));
+
+ /* Calculate next timeout */
+ if (sconn->retry_count >= 1) {
+ sconn->retry_timeout = sconn->retry_timeout * SILC_SERVER_RETRY_MULTIPLIER;
+ if (sconn->retry_timeout > param->reconnect_interval_max)
+ sconn->retry_timeout = param->reconnect_interval_max;
+ } else {
+ sconn->retry_timeout = param->reconnect_interval;
+ }
+ sconn->retry_count++;
+ sconn->retry_timeout = sconn->retry_timeout +
+ (silc_rng_get_rn32(server->rng) % SILC_SERVER_RETRY_RANDOMIZER);
+
+ /* If we've reached max retry count, give up. */
+ if ((sconn->retry_count > param->reconnect_count) &&
+ !param->reconnect_keep_trying) {
+ SILC_LOG_ERROR(("Could not connect, giving up"));
+ silc_server_connection_free(sconn);
+ return;
+ }
- /* Perform keepalive. */
- if (param->keepalive_secs)
- silc_socket_set_heartbeat(sock, param->keepalive_secs, server,
- silc_server_perform_heartbeat,
- server->schedule);
+ SILC_LOG_DEBUG(("Retrying connecting %d seconds", sconn->retry_timeout));
- /* Perform Quality of Service */
- if (param->qos)
- silc_socket_set_qos(sock, param->qos_rate_limit, param->qos_bytes_limit,
- param->qos_limit_sec, param->qos_limit_usec,
- server->schedule);
+ /* We will lookup a fresh pointer later */
+ silc_server_config_unref(&sconn->conn);
- out:
- if (sock->protocol == protocol)
- silc_protocol_free(protocol);
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- if (ctx->ske)
- silc_ske_free(ctx->ske);
- silc_free(ctx->dest_id);
- silc_server_config_unref(&ctx->cconfig);
- silc_server_config_unref(&ctx->sconfig);
- silc_server_config_unref(&ctx->rconfig);
- silc_free(ctx);
- sock->protocol = NULL;
+ /* Wait before retrying */
+ silc_schedule_task_del_by_context(server->schedule, sconn);
+ silc_schedule_task_add_timeout(server->schedule, silc_server_connect_router,
+ sconn, sconn->retry_timeout, 0);
}
-/* This function is used to read packets from network and send packets to
- network. This is usually a generic task. */
+/* Callback for async connection to remote router */
-SILC_TASK_CALLBACK(silc_server_packet_process)
+static void silc_server_connection_established(SilcNetStatus status,
+ SilcStream stream,
+ void *context)
{
- SilcServer server = (SilcServer)context;
- SilcSocketConnection sock = server->sockets[fd];
- SilcIDListData idata;
- SilcCipher cipher = NULL;
- SilcHmac hmac = NULL;
- SilcUInt32 sequence = 0;
- bool local_is_router;
- int ret;
-
- if (!sock) {
- SILC_LOG_DEBUG(("Unknown socket connection"));
- return;
- }
-
- /* Packet sending */
+ SilcServerConnection sconn = context;
+ SilcServer server = sconn->server;
- if (type == SILC_TASK_WRITE) {
- /* Do not send data to disconnected connection */
- if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
- SILC_LOG_DEBUG(("Disconnected socket connection, cannot send"));
- SILC_SET_CONNECTION_FOR_INPUT(server->schedule, fd);
- SILC_UNSET_OUTBUF_PENDING(sock);
- silc_buffer_clear(sock->outbuf);
- return;
- }
+ silc_schedule_task_del_by_context(server->schedule, sconn);
+ sconn->op = NULL;
- server->stat.packets_sent++;
-
- /* Send the packet */
- ret = silc_packet_send(sock, TRUE);
+ switch (status) {
+ case SILC_NET_OK:
+ SILC_LOG_DEBUG(("Connection to %s:%d established",
+ sconn->remote_host, sconn->remote_port));
- /* If returned -2 could not write to connection now, will do
- it later. */
- if (ret == -2)
- return;
+ /* Continue with key exchange protocol */
+ sconn->stream = stream;
+ silc_server_start_key_exchange(sconn);
+ break;
- /* The packet has been sent and now it is time to set the connection
- back to only for input. When there is again some outgoing data
- available for this connection it will be set for output as well.
- This call clears the output setting and sets it only for input. */
- SILC_SET_CONNECTION_FOR_INPUT(server->schedule, fd);
- SILC_UNSET_OUTBUF_PENDING(sock);
- silc_buffer_clear(sock->outbuf);
-
- if (ret == -1) {
- SILC_LOG_ERROR(("Error sending packet to connection "
- "%s:%d [%s]", sock->hostname, sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
-
- if (sock->user_data) {
- /* If backup then mark that resuming will not be allowed */
- if (server->server_type == SILC_ROUTER && !server->backup_router &&
- sock->type == SILC_SOCKET_TYPE_SERVER) {
- SilcServerEntry server_entry = sock->user_data;
- if (server_entry->server_type == SILC_BACKUP_ROUTER)
- server->backup_closed = TRUE;
- }
+ case SILC_NET_UNKNOWN_IP:
+ case SILC_NET_UNKNOWN_HOST:
+ SILC_LOG_ERROR(("Could not connect to %s:%d: %s",
+ sconn->remote_host, sconn->remote_port,
+ silc_net_get_error_string(status)));
+ silc_server_connection_free(sconn);
+ break;
- silc_server_free_sock_user_data(server, sock, NULL);
- }
- SILC_SET_DISCONNECTING(sock);
- silc_server_close_connection(server, sock);
+ default:
+ SILC_LOG_ERROR(("Could not connect to %s:%d: %s",
+ sconn->remote_host, sconn->remote_port,
+ silc_net_get_error_string(status)));
+ if (!sconn->no_reconnect) {
+ silc_schedule_task_add_timeout(sconn->server->schedule,
+ silc_server_connect_to_router_retry,
+ sconn, 1, 0);
+ } else {
+ silc_server_connection_free(sconn);
}
- return;
+ break;
}
+}
- /* Packet receiving */
-
- /* Read some data from connection */
- ret = silc_packet_receive(sock);
- if (ret < 0) {
+/* Generic routine to use connect to a router. */
- if (ret == -1) {
- SILC_LOG_ERROR(("Error receiving packet from connection "
- "%s:%d [%s] %s", sock->hostname, sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router"), strerror(errno)));
+SILC_TASK_CALLBACK(silc_server_connect_router)
+{
+ SilcServerConnection sconn = context;
+ SilcServer server = sconn->server;
+ SilcServerConfigRouter *rconn;
- if (sock->user_data) {
- /* If backup then mark that resuming will not be allowed */
- if (server->server_type == SILC_ROUTER && !server->backup_router &&
- sock->type == SILC_SOCKET_TYPE_SERVER) {
- SilcServerEntry server_entry = sock->user_data;
- if (server_entry->server_type == SILC_BACKUP_ROUTER)
- server->backup_closed = TRUE;
- }
+ silc_schedule_task_del_by_context(server->schedule, sconn);
- silc_server_free_sock_user_data(server, sock, NULL);
- }
- SILC_SET_DISCONNECTING(sock);
- silc_server_close_connection(server, sock);
- }
+ /* Don't connect if we are shutting down. */
+ if (server->server_shutdown) {
+ silc_server_connection_free(sconn);
return;
}
- /* EOF */
- if (ret == 0) {
- SILC_LOG_DEBUG(("Read EOF"));
+ SILC_LOG_INFO(("Connecting to the %s %s on port %d",
+ (sconn->backup ? "backup router" : "router"),
+ sconn->remote_host, sconn->remote_port));
- /* If connection is disconnecting already we will finally
- close the connection */
- if (SILC_IS_DISCONNECTING(sock)) {
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- silc_server_close_connection(server, sock);
+ if (!server->no_conf) {
+ /* Find connection configuration */
+ rconn = silc_server_config_find_router_conn(server, sconn->remote_host,
+ sconn->remote_port);
+ if (!rconn) {
+ SILC_LOG_INFO(("Unconfigured %s connection %s:%d, cannot connect",
+ (sconn->backup ? "backup router" : "router"),
+ sconn->remote_host, sconn->remote_port));
+ silc_server_connection_free(sconn);
return;
}
-
- SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
-
- if (sock->user_data) {
- char tmp[128];
-
- /* If backup disconnected then mark that resuming will not be allowed */
- if (server->server_type == SILC_ROUTER && !server->backup_router &&
- sock->type == SILC_SOCKET_TYPE_SERVER && sock->user_data) {
- SilcServerEntry server_entry = sock->user_data;
- if (server_entry->server_type == SILC_BACKUP_ROUTER)
- server->backup_closed = TRUE;
- }
-
- if (silc_socket_get_error(sock, tmp, sizeof(tmp) - 1))
- silc_server_free_sock_user_data(server, sock, tmp);
- else
- silc_server_free_sock_user_data(server, sock, NULL);
- } else if (server->router_conn && server->router_conn->sock == sock &&
- !server->router && server->standalone) {
- silc_server_create_connections(server);
- }
-
- SILC_SET_DISCONNECTING(sock);
- silc_server_close_connection(server, sock);
- return;
+ silc_server_config_ref(&sconn->conn, server->config, (void *)rconn);
}
- /* If connection is disconnecting or disconnected we will ignore
- what we read. */
- if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
- SILC_LOG_DEBUG(("Ignoring read data from disconnected connection"));
+ /* Connect to remote host */
+ sconn->op =
+ silc_net_tcp_connect((!server->config->server_info->primary ? NULL :
+ server->config->server_info->primary->server_ip),
+ sconn->remote_host, sconn->remote_port,
+ server->schedule, silc_server_connection_established,
+ sconn);
+ if (!sconn->op) {
+ SILC_LOG_ERROR(("Could not connect to router %s:%d",
+ sconn->remote_host, sconn->remote_port));
+ silc_server_connection_free(sconn);
return;
}
- /* Get keys and stuff from ID entry */
- idata = (SilcIDListData)sock->user_data;
- if (idata) {
- cipher = idata->receive_key;
- hmac = idata->hmac_receive;
- sequence = idata->psn_receive;
- }
-
- /* Then, process the packet. This will call the parser that will then
- decrypt and parse the packet. */
-
- local_is_router = (server->server_type == SILC_ROUTER);
-
- /* If socket connection is our primary, we are backup and we are doing
- backup resuming, we won't process the packet as being a router
- (affects channel message decryption). */
- if (server->backup_router && SILC_SERVER_IS_BACKUP(sock) &&
- SILC_PRIMARY_ROUTE(server) == sock)
- local_is_router = FALSE;
-
- ret = silc_packet_receive_process(sock, local_is_router,
- cipher, hmac, sequence,
- silc_server_packet_parse, server);
-
- /* If processing failed the connection is closed. */
- if (!ret) {
- /* On packet processing errors we may close our primary router
- connection but won't become primary router if we are the backup
- since this is local error condition. */
- if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router)
- server->backup_noswitch = TRUE;
-
- if (sock->user_data) {
- /* If we are router and backup errorred then mark that resuming
- will not be allowed */
- if (server->server_type == SILC_ROUTER && !server->backup_router &&
- sock->type == SILC_SOCKET_TYPE_SERVER) {
- SilcServerEntry server_entry = sock->user_data;
- if (server_entry->server_type == SILC_BACKUP_ROUTER)
- server->backup_closed = TRUE;
- }
-
- silc_server_free_sock_user_data(server, sock, NULL);
- }
- SILC_SET_DISCONNECTING(sock);
- silc_server_close_connection(server, sock);
- }
+ /* Add to connection list */
+ silc_dlist_add(server->conns, sconn);
}
-/* Parses whole packet, received earlier. */
+/* This function connects to our primary router or if we are a router this
+ establishes all our primary routes. This is called at the start of the
+ server to do authentication and key exchange with our router - called
+ from schedule. */
-SILC_TASK_CALLBACK(silc_server_packet_parse_real)
+SILC_TASK_CALLBACK(silc_server_connect_to_router)
{
- SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
- SilcServer server = (SilcServer)parse_ctx->context;
- SilcSocketConnection sock = parse_ctx->sock;
- SilcPacketContext *packet = parse_ctx->packet;
- SilcIDListData idata = (SilcIDListData)sock->user_data;
- int ret;
-
- if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
- SILC_LOG_DEBUG(("Connection is disconnected"));
- goto out;
- }
+ SilcServer server = context;
+ SilcServerConnection sconn;
+ SilcServerConfigRouter *ptr;
- server->stat.packets_received++;
+ /* Don't connect if we are shutting down. */
+ if (server->server_shutdown)
+ return;
- /* Parse the packet */
- if (parse_ctx->normal)
- ret = silc_packet_parse(packet, idata ? idata->receive_key : NULL);
- else
- ret = silc_packet_parse_special(packet, idata ? idata->receive_key : NULL);
+ SILC_LOG_DEBUG(("We are %s",
+ (server->server_type == SILC_SERVER ?
+ "normal server" : server->server_type == SILC_ROUTER ?
+ "router" : "backup router/normal server")));
- /* If entry is disabled ignore what we got. */
- if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED &&
- ret != SILC_PACKET_HEARTBEAT && ret != SILC_PACKET_RESUME_ROUTER &&
- ret != SILC_PACKET_REKEY && ret != SILC_PACKET_REKEY_DONE &&
- ret != SILC_PACKET_KEY_EXCHANGE_1 && ret != SILC_PACKET_KEY_EXCHANGE_2) {
- SILC_LOG_DEBUG(("Connection is disabled (packet %s dropped)",
- silc_get_packet_name(ret)));
- goto out;
+ /* XXX */
+ if (!server->config->routers) {
+ /* There wasn't a configured router, we will continue but we don't
+ have a connection to outside world. We will be standalone server. */
+ SILC_LOG_DEBUG(("No router(s), we are standalone"));
+ server->standalone = TRUE;
+ return;
}
- if (ret == SILC_PACKET_NONE) {
- SILC_LOG_DEBUG(("Error parsing packet"));
- goto out;
- }
+ /* Create the connections to all our routes */
+ for (ptr = server->config->routers; ptr; ptr = ptr->next) {
- /* Check that the the current client ID is same as in the client's packet. */
- if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
- SilcClientEntry client = (SilcClientEntry)sock->user_data;
- if (client && client->id && packet->src_id) {
- void *id = silc_id_str2id(packet->src_id, packet->src_id_len,
- packet->src_id_type);
- if (!id || !SILC_ID_CLIENT_COMPARE(client->id, id)) {
- silc_free(id);
- SILC_LOG_DEBUG(("Packet source is not same as sender"));
- goto out;
- }
- silc_free(id);
- }
- }
+ SILC_LOG_DEBUG(("%s connection [%s] %s:%d",
+ ptr->backup_router ? "Backup router" : "Router",
+ ptr->initiator ? "Initiator" : "Responder",
+ ptr->host, ptr->port));
- if (server->server_type == SILC_ROUTER) {
- /* Route the packet if it is not destined to us. Other ID types but
- server are handled separately after processing them. */
- if (packet->dst_id && !(packet->flags & SILC_PACKET_FLAG_BROADCAST) &&
- packet->dst_id_type == SILC_ID_SERVER &&
- sock->type != SILC_SOCKET_TYPE_CLIENT &&
- memcmp(packet->dst_id, server->id_string, server->id_string_len)) {
- SilcSocketConnection conn;
+ if (server->server_type == SILC_ROUTER && ptr->backup_router &&
+ ptr->initiator == FALSE && !server->backup_router &&
+ !silc_server_config_get_backup_router(server))
+ server->wait_backup = TRUE;
- /* Route the packet to fastest route for the destination ID */
- void *id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- packet->dst_id_type);
- if (!id)
- goto out;
+ if (!ptr->initiator)
+ continue;
- conn = silc_server_route_get(server, id, packet->dst_id_type);
- if (!conn) {
- SILC_LOG_WARNING(("Packet to unknown server ID %s, dropped (no route)",
- silc_id_render(id, SILC_ID_SERVER)));
- goto out;
+ /* Check whether we are connecting or connected to this host already */
+ if (silc_server_num_sockets_by_remote(server,
+ silc_net_is_ip(ptr->host) ?
+ ptr->host : NULL,
+ silc_net_is_ip(ptr->host) ?
+ NULL : ptr->host, ptr->port)) {
+ SILC_LOG_DEBUG(("We are already connected to %s:%d",
+ ptr->host, ptr->port));
+
+ /* If we don't have primary router and this connection is our
+ primary router we are in desync. Reconnect to the primary. */
+ if (server->standalone && !server->router) {
+ /* XXX */
+ SilcPacketStream sock;
+ SilcServerConfigRouter *primary =
+ silc_server_config_get_primary_router(server);
+ if (primary != ptr)
+ continue;
+ sock = silc_server_find_socket_by_host(server, SILC_CONN_ROUTER,
+ ptr->host, ptr->port);
+ if (!sock)
+ continue;
+ server->backup_noswitch = TRUE;
+#if 0
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_disconnect_remote(server, sock, 0, NULL);
+#endif /* 0 */
+ server->backup_noswitch = FALSE;
+ SILC_LOG_DEBUG(("Reconnecting to primary router"));
+ } else {
+ continue;
}
+ }
- silc_server_packet_route(server, conn, packet);
- silc_free(id);
- goto out;
+ /* Allocate connection object for hold connection specific stuff. */
+ sconn = silc_calloc(1, sizeof(*sconn));
+ if (!sconn)
+ continue;
+ sconn->remote_host = strdup(ptr->host);
+ sconn->remote_port = ptr->port;
+ sconn->backup = ptr->backup_router;
+ if (sconn->backup) {
+ sconn->backup_replace_ip = strdup(ptr->backup_replace_ip);
+ sconn->backup_replace_port = ptr->backup_replace_port;
}
+
+ /* XXX */
+ if (!server->router_conn && !sconn->backup)
+ server->router_conn = sconn;
+
+ /* Connect */
+ silc_server_connect_router(server->schedule, server, SILC_TASK_EXPIRE,
+ 0, sconn);
}
+}
- /* Parse the incoming packet type */
- silc_server_packet_parse_type(server, sock, packet);
- /* Broadcast packet if it is marked as broadcast packet and it is
- originated from router and we are router. */
- if (server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_ROUTER &&
- packet->flags & SILC_PACKET_FLAG_BROADCAST) {
- /* Broadcast to our primary route */
- silc_server_packet_broadcast(server, SILC_PRIMARY_ROUTE(server), packet);
+/************************ Accepting new connection **************************/
- /* If we have backup routers then we need to feed all broadcast
- data to those servers. */
- silc_server_backup_broadcast(server, sock, packet);
- }
+/* After this is called, server don't wait for backup router anymore.
+ This gets called automatically even after we have backup router
+ connection established. */
- out:
- silc_packet_context_free(packet);
- silc_free(parse_ctx);
+SILC_TASK_CALLBACK(silc_server_backup_router_wait)
+{
+ SilcServer server = context;
+ server->wait_backup = FALSE;
}
-/* Parser callback called by silc_packet_receive_process. This merely
- registers timeout that will handle the actual parsing when appropriate. */
+/* Authentication data callback */
-bool silc_server_packet_parse(SilcPacketParserContext *parser_context,
- void *context)
+static SilcBool
+silc_server_accept_get_auth(SilcConnAuth connauth,
+ SilcConnectionType conn_type,
+ unsigned char **passphrase,
+ SilcUInt32 *passphrase_len,
+ SilcSKR *repository,
+ void *context)
{
- SilcServer server = (SilcServer)context;
- SilcSocketConnection sock = parser_context->sock;
- SilcIDListData idata = (SilcIDListData)sock->user_data;
- bool ret;
+ SilcPacketStream sock = context;
+ SilcUnknownEntry entry = silc_packet_get_context(sock);
+ SilcServer server = entry->server;
- if (idata)
- idata->psn_receive = parser_context->packet->sequence + 1;
+ SILC_LOG_DEBUG(("Remote connection type %d", conn_type));
- /* If protocol for this connection is key exchange or rekey then we'll
- process all packets synchronously, since there might be packets in
- queue that we are not able to decrypt without first processing the
- packets before them. */
- if (sock->protocol && sock->protocol->protocol &&
- (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE ||
- sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)) {
- silc_server_packet_parse_real(server->schedule, server, 0, sock->sock,
- parser_context);
-
- if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
- SILC_LOG_DEBUG(("Connection is disconnected"));
+ /* Remote end is client */
+ if (conn_type == SILC_CONN_CLIENT) {
+ SilcServerConfigClient *cconfig = entry->cconfig.ref_ptr;
+ if (!cconfig)
return FALSE;
- }
- /* Reprocess data since we'll return FALSE here. This is because
- the idata->receive_key might have become valid in the last packet
- and we want to call this processor with valid cipher. */
- if (idata)
- ret = silc_packet_receive_process(
- sock, server->server_type == SILC_ROUTER,
- idata->receive_key,
- idata->hmac_receive, idata->psn_receive,
- silc_server_packet_parse, server);
- else
- ret = silc_packet_receive_process(
- sock, server->server_type == SILC_ROUTER,
- NULL, NULL, 0,
- silc_server_packet_parse, server);
-
- if (!ret) {
- /* On packet processing errors we may close our primary router
- connection but won't become primary router if we are the backup
- since this is local error condition. */
- if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router)
- server->backup_noswitch = TRUE;
+ *passphrase = cconfig->passphrase;
+ *passphrase_len = cconfig->passphrase_len;
+ if (cconfig->publickeys)
+ *repository = server->repository;
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- SILC_SET_DISCONNECTING(sock);
- silc_server_close_connection(server, sock);
- }
+ entry->data.conn_type = conn_type;
+ return TRUE;
+ }
- return FALSE;
+ /* Remote end is server */
+ if (conn_type == SILC_CONN_SERVER) {
+ SilcServerConfigServer *sconfig = entry->sconfig.ref_ptr;
+ if (!sconfig)
+ return FALSE;
+
+ *passphrase = sconfig->passphrase;
+ *passphrase_len = sconfig->passphrase_len;
+ if (sconfig->publickeys)
+ *repository = server->repository;
+
+ entry->data.conn_type = conn_type;
+ return TRUE;
}
- switch (sock->type) {
- case SILC_SOCKET_TYPE_UNKNOWN:
- case SILC_SOCKET_TYPE_CLIENT:
- /* Parse the packet with timeout */
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_packet_parse_real,
- (void *)parser_context, 0, 100000,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- break;
- case SILC_SOCKET_TYPE_SERVER:
- case SILC_SOCKET_TYPE_ROUTER:
- /* Packets from servers are parsed immediately */
- silc_server_packet_parse_real(server->schedule, server, 0, sock->sock,
- parser_context);
- break;
+ /* Remote end is router */
+ if (conn_type == SILC_CONN_ROUTER) {
+ SilcServerConfigRouter *rconfig = entry->rconfig.ref_ptr;
+ if (!rconfig)
+ return FALSE;
+
+ *passphrase = rconfig->passphrase;
+ *passphrase_len = rconfig->passphrase_len;
+ if (rconfig->publickeys)
+ *repository = server->repository;
+
+ entry->data.conn_type = conn_type;
+ return TRUE;
}
- return TRUE;
+ return FALSE;
}
-/* Parses the packet type and calls what ever routines the packet type
- requires. This is done for all incoming packets. */
+/* Authentication completion callback. */
-void silc_server_packet_parse_type(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+static void
+silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
+ void *context)
{
- SilcPacketType type = packet->type;
- SilcIDListData idata = (SilcIDListData)sock->user_data;
+ SilcPacketStream sock = context;
+ SilcUnknownEntry entry = silc_packet_get_context(sock);
+ SilcServer server = entry->server;
+ SilcServerConfigConnParams *param;
+ void *id_entry;
- SILC_LOG_DEBUG(("Received %s packet [flags %d]",
- silc_get_packet_name(type), packet->flags));
+ if (success == FALSE) {
+ /* Authentication failed */
+ SILC_LOG_INFO(("Authentication failed for %s (%s) [%s]", entry->hostname,
+ entry->ip, SILC_CONNTYPE_STRING(entry->data.conn_type)));
+ server->stat.auth_failures++;
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+ goto out;
+ }
- /* Parse the packet type */
- switch (type) {
- case SILC_PACKET_DISCONNECT:
+ SILC_LOG_DEBUG(("Checking whether connection is allowed"));
+
+ switch (entry->data.conn_type) {
+ case SILC_CONN_CLIENT:
{
- SilcStatus status;
- char *message = NULL;
+ SilcClientEntry client;
+ SilcServerConfigClient *conn = entry->cconfig.ref_ptr;
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- if (packet->buffer->len < 1)
- break;
+ /* Verify whether this connection is after all allowed to connect */
+ if (!silc_server_connection_allowed(server, sock, entry->data.conn_type,
+ &server->config->param,
+ conn->param,
+ silc_connauth_get_ske(connauth))) {
+ server->stat.auth_failures++;
+ goto out;
+ }
- status = (SilcStatus)packet->buffer->data[0];
- if (packet->buffer->len > 1 &&
- silc_utf8_valid(packet->buffer->data + 1, packet->buffer->len - 1))
- message = silc_memdup(packet->buffer->data + 1,
- packet->buffer->len - 1);
+ /* If we are primary router and we have backup router configured
+ but it has not connected to use yet, do not accept any other
+ connection. */
+ if (server->wait_backup && server->server_type == SILC_ROUTER &&
+ !server->backup_router) {
+ SilcServerConfigRouter *router;
+ router = silc_server_config_get_backup_router(server);
+ if (router && strcmp(server->config->server_info->primary->server_ip,
+ entry->ip) &&
+ silc_server_find_socket_by_host(server,
+ SILC_CONN_SERVER,
+ router->backup_replace_ip, 0)) {
+ SILC_LOG_INFO(("Will not accept connections because we do "
+ "not have backup router connection established"));
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_PERM_DENIED,
+ "We do not have connection to backup "
+ "router established, try later");
+ server->stat.auth_failures++;
- SILC_LOG_INFO(("Disconnected by %s (%s): %s (%d) %s",
- sock->ip, sock->hostname,
- silc_get_status_message(status), status,
- message ? message : ""));
- silc_free(message);
+ /* From here on, wait 20 seconds for the backup router to appear. */
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_router_wait,
+ (void *)server, 20, 0);
+ goto out;
+ }
+ }
- /* Do not switch to backup in case of error */
- server->backup_noswitch = (status == SILC_STATUS_OK ? FALSE : TRUE);
+ SILC_LOG_DEBUG(("Remote host is client"));
+ SILC_LOG_INFO(("Connection %s (%s) is client", entry->hostname,
+ entry->ip));
- /* If backup disconnected then mark that resuming will not be allowed */
- if (server->server_type == SILC_ROUTER && !server->backup_router &&
- sock->type == SILC_SOCKET_TYPE_SERVER && sock->user_data) {
- SilcServerEntry server_entry = sock->user_data;
- if (server_entry->server_type == SILC_BACKUP_ROUTER)
- server->backup_closed = TRUE;
+ /* Add the client to the client ID cache. The nickname and Client ID
+ and other information is created after we have received NEW_CLIENT
+ packet from client. */
+ client = silc_idlist_add_client(server->local_list,
+ NULL, NULL, NULL, NULL, NULL, sock);
+ if (!client) {
+ SILC_LOG_ERROR(("Could not add new client to cache"));
+ server->stat.auth_failures++;
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_AUTH_FAILED, NULL);
+ goto out;
}
+ entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
- /* Handle the disconnection from our end too */
- if (sock->user_data && SILC_IS_LOCAL(sock->user_data))
- silc_server_free_sock_user_data(server, sock, NULL);
- SILC_SET_DISCONNECTING(sock);
- silc_server_close_connection(server, sock);
- server->backup_noswitch = FALSE;
- }
- break;
-
- case SILC_PACKET_SUCCESS:
- /*
- * Success received for something. For now we can have only
- * one protocol for connection executing at once hence this
- * success message is for whatever protocol is executing currently.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- if (sock->protocol)
- silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
- break;
+ /* Statistics */
+ server->stat.my_clients++;
+ server->stat.clients++;
+ server->stat.cell_clients++;
- case SILC_PACKET_FAILURE:
- /*
- * Failure received for something. For now we can have only
- * one protocol for connection executing at once hence this
- * failure message is for whatever protocol is executing currently.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
+ /* Get connection parameters */
+ if (conn->param) {
+ param = conn->param;
- /* Check for failure START_USE from backup router */
- if (server->server_type == SILC_SERVER &&
- server->backup_primary && packet->buffer->len == 4) {
- SilcUInt32 type;
- SILC_GET32_MSB(type, packet->buffer->data);
- if (type == SILC_SERVER_BACKUP_START_USE) {
- /* Attempt to reconnect to primary */
- SILC_LOG_DEBUG(("Received failed START_USE from backup %s", sock->ip));
-
- /* Default action is to disconnect from backup and reconnect to
- primary. Since this failure can happen during switching to
- backup (backup might have not noticed the primary going down yet),
- we will wait a while and keep sending START_USE to backup.
- Only after that we'll give up. */
- if (server->router == sock->user_data &&
- (time(0) - server->router_connect) < 30) {
- SILC_LOG_DEBUG(("Resending START_USE to backup router"));
- silc_server_backup_send_start_use(server, sock, FALSE);
- break;
- }
+ if (!param->keepalive_secs)
+ param->keepalive_secs = server->config->param.keepalive_secs;
- /* If backup is our primary, disconnect now. */
- if (server->router == sock->user_data) {
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- SILC_SET_DISCONNECTING(sock);
- silc_server_close_connection(server, sock);
+ if (!param->qos && server->config->param.qos) {
+ param->qos = server->config->param.qos;
+ param->qos_rate_limit = server->config->param.qos_rate_limit;
+ param->qos_bytes_limit = server->config->param.qos_bytes_limit;
+ param->qos_limit_sec = server->config->param.qos_limit_sec;
+ param->qos_limit_usec = server->config->param.qos_limit_usec;
}
- /* Reconnect */
- silc_server_create_connections(server);
+ /* Check if to be anonymous connection */
+ if (param->anonymous)
+ client->mode |= SILC_UMODE_ANONYMOUS;
}
- }
- /* Execute protocol */
- if (sock->protocol) {
- sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
- silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
+ /* Add public key to hash list (for whois using attributes) */
+ if (!silc_hash_table_find_by_context(server->pk_hash,
+ entry->data.public_key,
+ client, NULL))
+ silc_hash_table_add(server->pk_hash,
+ entry->data.public_key, client);
+
+ id_entry = (void *)client;
break;
}
- break;
- case SILC_PACKET_REJECT:
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- return;
- break;
+ case SILC_CONN_SERVER:
+ case SILC_CONN_ROUTER:
+ {
+ SilcServerEntry new_server;
+ SilcBool initiator = FALSE;
+ SilcBool backup_local = FALSE;
+ SilcBool backup_router = FALSE;
+ char *backup_replace_ip = NULL;
+ SilcUInt16 backup_replace_port = 0;
+ SilcServerConfigServer *sconn = entry->sconfig.ref_ptr;
+ SilcServerConfigRouter *rconn = entry->rconfig.ref_ptr;
- case SILC_PACKET_NOTIFY:
- /*
- * Received notify packet. Server can receive notify packets from
- * router. Server then relays the notify messages to clients if needed.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- silc_server_notify_list(server, sock, packet);
- else
- silc_server_notify(server, sock, packet);
- break;
+ /* If we are backup router and this is incoming server connection
+ and we do not have connection to primary router, do not allow
+ the connection. */
+ if (server->server_type == SILC_BACKUP_ROUTER &&
+ entry->data.conn_type == SILC_CONN_SERVER &&
+ !SILC_PRIMARY_ROUTE(server)) {
+ SILC_LOG_INFO(("Will not accept server connection because we do "
+ "not have primary router connection established"));
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_PERM_DENIED,
+ "We do not have connection to primary "
+ "router established, try later");
+ server->stat.auth_failures++;
+ goto out;
+ }
- /*
- * Channel packets
- */
- case SILC_PACKET_CHANNEL_MESSAGE:
- /*
- * Received channel message. Channel messages are special packets
- * (although probably most common ones) thus they are handled
- * specially.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- idata->last_receive = time(NULL);
- silc_server_channel_message(server, sock, packet);
- break;
+ if (entry->data.conn_type == SILC_CONN_ROUTER) {
+ /* Verify whether this connection is after all allowed to connect */
+ if (!silc_server_connection_allowed(server, sock,
+ entry->data.conn_type,
+ &server->config->param,
+ rconn ? rconn->param : NULL,
+ silc_connauth_get_ske(connauth))) {
+ server->stat.auth_failures++;
+ goto out;
+ }
- case SILC_PACKET_CHANNEL_KEY:
- /*
- * Received key for channel. As channels are created by the router
- * the keys are as well. We will distribute the key to all of our
- * locally connected clients on the particular channel. Router
- * never receives this channel and thus is ignored.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- silc_server_channel_key(server, sock, packet);
- break;
+ if (rconn) {
+ if (rconn->param) {
+ param = rconn->param;
- /*
- * Command packets
- */
- case SILC_PACKET_COMMAND:
- /*
- * Recived command. Processes the command request and allocates the
- * command context and calls the command.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- server->stat.commands_received++;
- silc_server_command_process(server, sock, packet);
- break;
+ if (!param->keepalive_secs)
+ param->keepalive_secs = server->config->param.keepalive_secs;
- case SILC_PACKET_COMMAND_REPLY:
- /*
- * Received command reply packet. Received command reply to command. It
- * may be reply to command sent by us or reply to command sent by client
- * that we've routed further.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- server->stat.commands_received++;
- silc_server_command_reply(server, sock, packet);
- break;
+ if (!param->qos && server->config->param.qos) {
+ param->qos = server->config->param.qos;
+ param->qos_rate_limit = server->config->param.qos_rate_limit;
+ param->qos_bytes_limit = server->config->param.qos_bytes_limit;
+ param->qos_limit_sec = server->config->param.qos_limit_sec;
+ param->qos_limit_usec = server->config->param.qos_limit_usec;
+ }
+ }
- /*
- * Private Message packets
- */
- case SILC_PACKET_PRIVATE_MESSAGE:
- /*
- * Received private message packet. The packet is coming from either
- * client or server.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- idata->last_receive = time(NULL);
- silc_server_private_message(server, sock, packet);
- break;
+ initiator = rconn->initiator;
+ backup_local = rconn->backup_local;
+ backup_router = rconn->backup_router;
+ backup_replace_ip = rconn->backup_replace_ip;
+ backup_replace_port = rconn->backup_replace_port;
+ }
+ }
- case SILC_PACKET_PRIVATE_MESSAGE_KEY:
- /*
- * Private message key packet.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- silc_server_private_message_key(server, sock, packet);
- break;
+ if (entry->data.conn_type == SILC_CONN_SERVER) {
+ /* Verify whether this connection is after all allowed to connect */
+ if (!silc_server_connection_allowed(server, sock,
+ entry->data.conn_type,
+ &server->config->param,
+ sconn ? sconn->param : NULL,
+ silc_connauth_get_ske(connauth))) {
+ server->stat.auth_failures++;
+ goto out;
+ }
+ if (sconn) {
+ if (sconn->param) {
+ param = sconn->param;
- /*
- * Key Exchange protocol packets
- */
- case SILC_PACKET_KEY_EXCHANGE:
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
+ if (!param->keepalive_secs)
+ param->keepalive_secs = server->config->param.keepalive_secs;
- if (sock->protocol && sock->protocol->protocol &&
- sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE) {
- SilcServerKEInternalContext *proto_ctx =
- (SilcServerKEInternalContext *)sock->protocol->context;
+ if (!param->qos && server->config->param.qos) {
+ param->qos = server->config->param.qos;
+ param->qos_rate_limit = server->config->param.qos_rate_limit;
+ param->qos_bytes_limit = server->config->param.qos_bytes_limit;
+ param->qos_limit_sec = server->config->param.qos_limit_sec;
+ param->qos_limit_usec = server->config->param.qos_limit_usec;
+ }
+ }
- proto_ctx->packet = silc_packet_context_dup(packet);
+ backup_router = sconn->backup_router;
+ }
+ }
- /* Let the protocol handle the packet */
- silc_protocol_execute(sock->protocol, server->schedule, 0, 100000);
- } else {
- SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
- "protocol active (%s:%d [%s]).", sock->hostname,
- sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
- }
- break;
+ /* If we are primary router and we have backup router configured
+ but it has not connected to use yet, do not accept any other
+ connection. */
+#if 0
+ if (server->wait_backup && server->server_type == SILC_ROUTER &&
+ !server->backup_router && !backup_router) {
+ SilcServerConfigRouter *router;
+ router = silc_server_config_get_backup_router(server);
+ if (router && strcmp(server->config->server_info->primary->server_ip,
+ ip) &&
+ silc_server_find_socket_by_host(server,
+ SILC_CONN_SERVER,
+ router->backup_replace_ip, 0)) {
+ SILC_LOG_INFO(("Will not accept connections because we do "
+ "not have backup router connection established"));
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_PERM_DENIED,
+ "We do not have connection to backup "
+ "router established, try later");
+ server->stat.auth_failures++;
- case SILC_PACKET_KEY_EXCHANGE_1:
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
+ /* From here on, wait 20 seconds for the backup router to appear. */
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_router_wait,
+ (void *)server, 20, 0);
+ goto out;
+ }
+ }
+#endif /* 0 */
+
+ SILC_LOG_DEBUG(("Remote host is %s",
+ entry->data.conn_type == SILC_CONN_SERVER ?
+ "server" : (backup_router ?
+ "backup router" : "router")));
+ SILC_LOG_INFO(("Connection %s (%s) is %s", entry->hostname,
+ entry->ip, entry->data.conn_type == SILC_CONN_SERVER ?
+ "server" : (backup_router ?
+ "backup router" : "router")));
+
+ /* Add the server into server cache. The server name and Server ID
+ is updated after we have received NEW_SERVER packet from the
+ server. We mark ourselves as router for this server if we really
+ are router. */
+ new_server =
+ silc_idlist_add_server((entry->data.conn_type == SILC_CONN_SERVER ?
+ server->local_list : (backup_router ?
+ server->local_list :
+ server->global_list)),
+ NULL,
+ (entry->data.conn_type == SILC_CONN_SERVER ?
+ SILC_SERVER : SILC_ROUTER),
+ NULL,
+ (entry->data.conn_type == SILC_CONN_SERVER ?
+ server->id_entry : (backup_router ?
+ server->id_entry : NULL)),
+ sock);
+ if (!new_server) {
+ SILC_LOG_ERROR(("Could not add new server to cache"));
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_AUTH_FAILED, NULL);
+ server->stat.auth_failures++;
+ goto out;
+ }
+ entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
- if (sock->protocol && sock->protocol->protocol &&
- (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE ||
- sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)) {
+ id_entry = (void *)new_server;
- if (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY) {
- SilcServerRekeyInternalContext *proto_ctx =
- (SilcServerRekeyInternalContext *)sock->protocol->context;
+ /* If the incoming connection is router and marked as backup router
+ then add it to be one of our backups */
+ if (entry->data.conn_type == SILC_CONN_ROUTER && backup_router) {
+ /* Change it back to SERVER type since that's what it really is. */
+ if (backup_local)
+ entry->data.conn_type = SILC_CONN_SERVER;
+ new_server->server_type = SILC_BACKUP_ROUTER;
- if (proto_ctx->packet)
- silc_packet_context_free(proto_ctx->packet);
+ SILC_SERVER_SEND_OPERS(server, FALSE, TRUE, SILC_NOTIFY_TYPE_NONE,
+ ("Backup router %s is now online",
+ entry->hostname));
- proto_ctx->packet = silc_packet_context_dup(packet);
+ /* Remove the backup waiting with timeout */
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_router_wait,
+ (void *)server, 10, 0);
+ }
- /* Let the protocol handle the packet */
- silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
+ /* Statistics */
+ if (entry->data.conn_type == SILC_CONN_SERVER) {
+ server->stat.my_servers++;
+ server->stat.servers++;
} else {
- SilcServerKEInternalContext *proto_ctx =
- (SilcServerKEInternalContext *)sock->protocol->context;
-
- if (proto_ctx->packet)
- silc_packet_context_free(proto_ctx->packet);
+ server->stat.my_routers++;
+ server->stat.routers++;
+ }
- proto_ctx->packet = silc_packet_context_dup(packet);
- proto_ctx->dest_id_type = packet->src_id_type;
- proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
- packet->src_id_type);
- if (!proto_ctx->dest_id)
+ /* Check whether this connection is to be our primary router connection
+ if we do not already have the primary route. */
+ if (!backup_router &&
+ server->standalone && entry->data.conn_type == SILC_CONN_ROUTER) {
+ if (silc_server_config_is_primary_route(server) && !initiator)
break;
- /* Let the protocol handle the packet */
- silc_protocol_execute(sock->protocol, server->schedule,
- 0, 100000);
+ SILC_LOG_DEBUG(("We are not standalone server anymore"));
+ server->standalone = FALSE;
+ if (!server->id_entry->router) {
+ server->id_entry->router = id_entry;
+ server->router = id_entry;
+ }
}
- } else {
- SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
- "protocol active (%s:%d [%s]).", sock->hostname,
- sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
- }
- break;
- case SILC_PACKET_KEY_EXCHANGE_2:
- if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
+ }
- if (sock->protocol && sock->protocol->protocol &&
- (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE ||
- sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)) {
-
- if (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY) {
- SilcServerRekeyInternalContext *proto_ctx =
- (SilcServerRekeyInternalContext *)sock->protocol->context;
-
- if (proto_ctx->packet)
- silc_packet_context_free(proto_ctx->packet);
-
- proto_ctx->packet = silc_packet_context_dup(packet);
+ default:
+ goto out;
+ break;
+ }
- /* Let the protocol handle the packet */
- silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
- } else {
- SilcServerKEInternalContext *proto_ctx =
- (SilcServerKEInternalContext *)sock->protocol->context;
+ /* Add the common data structure to the ID entry. */
+ silc_idlist_add_data(id_entry, (SilcIDListData)entry);
+ silc_packet_set_context(sock, id_entry);
- if (proto_ctx->packet)
- silc_packet_context_free(proto_ctx->packet);
+ /* Connection has been fully established now. Everything is ok. */
+ SILC_LOG_DEBUG(("New connection authenticated"));
- proto_ctx->packet = silc_packet_context_dup(packet);
- proto_ctx->dest_id_type = packet->src_id_type;
- proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
- packet->src_id_type);
- if (!proto_ctx->dest_id)
- break;
+ /* XXX Add connection to server->conns so that we know we have connection
+ to this peer. */
+ /* XXX */
- /* Let the protocol handle the packet */
- silc_protocol_execute(sock->protocol, server->schedule,
- 0, 100000);
- }
- } else {
- SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
- "protocol active (%s:%d [%s]).", sock->hostname,
- sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
- }
- break;
+#if 0
+ /* Perform keepalive. */
+ if (param->keepalive_secs)
+ silc_socket_set_heartbeat(sock, param->keepalive_secs, server,
+ silc_server_perform_heartbeat,
+ server->schedule);
- case SILC_PACKET_CONNECTION_AUTH_REQUEST:
- /*
- * Connection authentication request packet. When we receive this packet
- * we will send to the other end information about our mandatory
- * authentication method for the connection. This packet maybe received
- * at any time.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- silc_server_connection_auth_request(server, sock, packet);
- break;
+ /* Perform Quality of Service */
+ if (param->qos)
+ silc_socket_set_qos(sock, param->qos_rate_limit, param->qos_bytes_limit,
+ param->qos_limit_sec, param->qos_limit_usec,
+ server->schedule);
+#endif
- /*
- * Connection Authentication protocol packets
- */
- case SILC_PACKET_CONNECTION_AUTH:
- /* Start of the authentication protocol. We receive here the
- authentication data and will verify it. */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
+ silc_server_config_unref(&entry->cconfig);
+ silc_server_config_unref(&entry->sconfig);
+ silc_server_config_unref(&entry->rconfig);
+ silc_free(entry);
- if (sock->protocol && sock->protocol->protocol->type
- == SILC_PROTOCOL_SERVER_CONNECTION_AUTH) {
+ out:
+ silc_ske_free(silc_connauth_get_ske(connauth));
+ silc_connauth_free(connauth);
+}
- SilcServerConnAuthInternalContext *proto_ctx =
- (SilcServerConnAuthInternalContext *)sock->protocol->context;
+/* SKE completion callback. We set the new keys into use here. */
- proto_ctx->packet = silc_packet_context_dup(packet);
+static void
+silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status,
+ SilcSKESecurityProperties prop,
+ SilcSKEKeyMaterial keymat,
+ SilcSKERekeyMaterial rekey,
+ void *context)
+{
+ SilcPacketStream sock = context;
+ SilcUnknownEntry entry = silc_packet_get_context(sock);
+ SilcServer server = entry->server;
+ SilcConnAuth connauth;
+ SilcCipher send_key, receive_key;
+ SilcHmac hmac_send, hmac_receive;
+ SilcHash hash;
+
+ if (status != SILC_SKE_STATUS_OK) {
+ /* SKE failed */
+ SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
+ silc_ske_map_status(status), entry->hostname, entry->ip));
+ silc_ske_free(ske);
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+ return;
+ }
- /* Let the protocol handle the packet */
- silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
- } else {
- SILC_LOG_ERROR(("Received Connection Auth packet but no authentication "
- "protocol active (%s:%d [%s]).", sock->hostname,
- sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
- }
- break;
+ SILC_LOG_DEBUG(("Setting keys into use"));
- case SILC_PACKET_NEW_ID:
- /*
- * Received New ID packet. This includes some new ID that has been
- * created. It may be for client, server or channel. This is the way
- * to distribute information about new registered entities in the
- * SILC network.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- silc_server_new_id_list(server, sock, packet);
- else
- silc_server_new_id(server, sock, packet);
- break;
+ /* Set the keys into use. The data will be encrypted after this. */
+ if (!silc_ske_set_keys(ske, keymat, prop, &send_key, &receive_key,
+ &hmac_send, &hmac_receive, &hash)) {
+ /* Error setting keys */
+ silc_ske_free(ske);
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+ return;
+ }
+ silc_packet_set_keys(sock, send_key, receive_key, hmac_send,
+ hmac_receive, FALSE);
- case SILC_PACKET_NEW_CLIENT:
- /*
- * Received new client packet. This includes client information that
- * we will use to create initial client ID. After creating new
- * ID we will send it to the client.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- silc_server_new_client(server, sock, packet);
- break;
+ SILC_LOG_DEBUG(("Starting connection authentication"));
+ server->stat.auth_attempts++;
- case SILC_PACKET_NEW_SERVER:
- /*
- * Received new server packet. This includes Server ID and some other
- * information that we may save. This is received after server has
- * connected to us.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- silc_server_new_server(server, sock, packet);
- break;
+ connauth = silc_connauth_alloc(server->schedule, ske,
+ server->config->conn_auth_timeout);
+ if (!connauth) {
+ /** Error allocating auth protocol */
+ silc_ske_free(ske);
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ return;
+ }
- case SILC_PACKET_NEW_CHANNEL:
- /*
- * Received new channel packet. Information about new channel in the
- * network are distributed using this packet.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- silc_server_new_channel_list(server, sock, packet);
- else
- silc_server_new_channel(server, sock, packet);
- break;
+ /* Start connection authentication */
+ silc_connauth_responder(connauth, silc_server_accept_get_auth,
+ silc_server_accept_auth_compl, sock);
+}
- case SILC_PACKET_HEARTBEAT:
- /*
- * Received heartbeat.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- break;
+/* Accept new TCP connection */
- case SILC_PACKET_KEY_AGREEMENT:
- /*
- * Received heartbeat.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- silc_server_key_agreement(server, sock, packet);
- break;
+static void silc_server_accept_new_connection(SilcNetStatus status,
+ SilcStream stream,
+ void *context)
+{
+ SilcServer server = context;
+ SilcPacketStream packet_stream;
+ SilcServerConfigClient *cconfig = NULL;
+ SilcServerConfigServer *sconfig = NULL;
+ SilcServerConfigRouter *rconfig = NULL;
+ SilcServerConfigDeny *deny;
+ SilcUnknownEntry entry;
+ SilcSKE ske;
+ SilcSKEParamsStruct params;
+ char *hostname, *ip;
+ SilcUInt16 port;
- case SILC_PACKET_REKEY:
- /*
- * Received re-key packet. The sender wants to regenerate the session
- * keys.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- silc_server_rekey(server, sock, packet);
- break;
+ SILC_LOG_DEBUG(("Accepting new connection"));
- case SILC_PACKET_REKEY_DONE:
- /*
- * The re-key is done.
- */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
+ /* Check for maximum allowed connections */
+ server->stat.conn_attempts++;
+#if 0
+ if (silc_server_num_connections(server) >
+ server->config->param.connections_max) {
+ SILC_LOG_ERROR(("Refusing connection, server is full"));
+ server->stat.conn_failures++;
+ silc_stream_destroy(stream);
+ return;
+ }
+#endif
- if (sock->protocol && sock->protocol->protocol &&
- sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY) {
+ /* Get hostname, IP and port */
+ if (!silc_socket_stream_get_info(stream, NULL, (const char **)&hostname,
+ (const char **)&ip, &port)) {
+ /* Bad socket stream */
+ server->stat.conn_failures++;
+ silc_stream_destroy(stream);
+ return;
+ }
- SilcServerRekeyInternalContext *proto_ctx =
- (SilcServerRekeyInternalContext *)sock->protocol->context;
+ /* Create packet stream */
+ packet_stream = silc_packet_stream_create(server->packet_engine,
+ server->schedule, stream);
+ if (!packet_stream) {
+ SILC_LOG_ERROR(("Refusing connection, cannot create packet stream"));
+ server->stat.conn_failures++;
+ silc_stream_destroy(stream);
+ return;
+ }
+ server->stat.conn_num++;
- if (proto_ctx->packet)
- silc_packet_context_free(proto_ctx->packet);
+ /* Set source ID to packet stream */
+ if (!silc_packet_set_ids(packet_stream, SILC_ID_SERVER, &server->id,
+ 0, NULL)) {
+ /* Out of memory */
+ server->stat.conn_failures++;
+ silc_packet_stream_destroy(packet_stream);
+ return;
+ }
- proto_ctx->packet = silc_packet_context_dup(packet);
+ /* Check whether this connection is denied to connect to us. */
+ deny = silc_server_config_find_denied(server, ip);
+ if (!deny)
+ deny = silc_server_config_find_denied(server, hostname);
+ if (deny) {
+ /* The connection is denied */
+ SILC_LOG_INFO(("Connection %s (%s) is denied", hostname, ip));
+ silc_server_disconnect_remote(server, packet_stream,
+ SILC_STATUS_ERR_BANNED_FROM_SERVER,
+ deny->reason);
+ return;
+ }
- /* Let the protocol handle the packet */
- silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
- } else {
- SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
- "protocol active (%s:%d [%s]).", sock->hostname,
- sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
- }
- break;
+ /* Check whether we have configured this sort of connection at all. We
+ have to check all configurations since we don't know what type of
+ connection this is. */
+ if (!(cconfig = silc_server_config_find_client(server, ip)))
+ cconfig = silc_server_config_find_client(server, hostname);
+ if (!(sconfig = silc_server_config_find_server_conn(server, ip)))
+ sconfig = silc_server_config_find_server_conn(server, hostname);
+ if (server->server_type == SILC_ROUTER)
+ if (!(rconfig = silc_server_config_find_router_conn(server, ip, port)))
+ rconfig = silc_server_config_find_router_conn(server, hostname, port);
+ if (!cconfig && !sconfig && !rconfig) {
+ SILC_LOG_INFO(("Connection %s (%s) is not allowed", hostname, ip));
+ server->stat.conn_failures++;
+ silc_server_disconnect_remote(server, packet_stream,
+ SILC_STATUS_ERR_BANNED_FROM_SERVER, NULL);
+ return;
+ }
- case SILC_PACKET_FTP:
- /* FTP packet */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- silc_server_ftp(server, sock, packet);
- break;
+ /* The connection is allowed */
+ entry = silc_calloc(1, sizeof(*entry));
+ if (!entry) {
+ server->stat.conn_failures++;
+ silc_server_disconnect_remote(server, packet_stream,
+ SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ return;
+ }
+ entry->hostname = hostname;
+ entry->ip = ip;
+ entry->port = port;
+ entry->server = server;
+ silc_packet_set_context(packet_stream, entry);
- case SILC_PACKET_RESUME_CLIENT:
- /* Resume client */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- silc_server_resume_client(server, sock, packet);
- break;
+ silc_server_config_ref(&entry->cconfig, server->config, cconfig);
+ silc_server_config_ref(&entry->sconfig, server->config, sconfig);
+ silc_server_config_ref(&entry->rconfig, server->config, rconfig);
- case SILC_PACKET_RESUME_ROUTER:
- /* Resume router packet received. This packet is received for backup
- router resuming protocol. */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- silc_server_backup_resume_router(server, sock, packet);
- break;
+ /* Take flags for key exchange. Since we do not know what type of connection
+ this is, we go through all found configurations and use the global ones
+ as well. This will result always into strictest key exchange flags. */
+ memset(¶ms, 0, sizeof(params));
+ SILC_GET_SKE_FLAGS(cconfig, params.flags);
+ SILC_GET_SKE_FLAGS(sconfig, params.flags);
+ SILC_GET_SKE_FLAGS(rconfig, params.flags);
+ if (server->config->param.key_exchange_pfs)
+ params.flags |= SILC_SKE_SP_FLAG_PFS;
- default:
- SILC_LOG_ERROR(("Incorrect packet type %d, packet dropped", type));
- break;
+ SILC_LOG_INFO(("Incoming connection %s (%s)", hostname, ip));
+ server->stat.conn_attempts++;
+
+ /* Start SILC Key Exchange protocol */
+ SILC_LOG_DEBUG(("Starting key exchange protocol"));
+ ske = silc_ske_alloc(server->rng, server->schedule, server->repository,
+ server->public_key, server->private_key,
+ packet_stream);
+ if (!ske) {
+ server->stat.conn_failures++;
+ silc_server_disconnect_remote(server, packet_stream,
+ SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ return;
}
+ silc_ske_set_callbacks(ske, silc_server_verify_key,
+ silc_server_accept_completed, packet_stream);
+
+ /* Start key exchange protocol */
+ params.version = silc_version_string;
+ params.timeout_secs = server->config->key_exchange_timeout;
+ silc_ske_responder(ske, packet_stream, ¶ms);
}
-/* Creates connection to a remote router. */
-void silc_server_create_connection(SilcServer server,
- const char *remote_host, SilcUInt32 port)
+/********************************** Rekey ***********************************/
+
+/* Initiator rekey completion callback */
+
+static void silc_server_rekey_completion(SilcSKE ske,
+ SilcSKEStatus status,
+ const SilcSKESecurityProperties prop,
+ const SilcSKEKeyMaterial keymat,
+ SilcSKERekeyMaterial rekey,
+ void *context)
{
- SilcServerConnection sconn;
+ SilcPacketStream sock = context;
+ SilcIDListData idata = silc_packet_get_context(sock);
+ SilcServer server = idata->sconn->server;
+
+ idata->sconn->op = NULL;
+ if (status != SILC_SKE_STATUS_OK) {
+ SILC_LOG_ERROR(("Error during rekey protocol with %s",
+ idata->sconn->remote_host));
+ return;
+ }
- /* Allocate connection object for hold connection specific stuff. */
- sconn = silc_calloc(1, sizeof(*sconn));
- sconn->remote_host = strdup(remote_host);
- sconn->remote_port = port;
- sconn->no_reconnect = TRUE;
+ SILC_LOG_DEBUG(("Rekey protocol completed with %s:%d [%s]",
+ idata->sconn->remote_host, idata->sconn->remote_port,
+ SILC_CONNTYPE_STRING(idata->conn_type)));
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_router,
- (void *)sconn, 0, 1, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ /* Save rekey data for next rekey */
+ idata->rekey = rekey;
+
+ /* Register new rekey timeout */
+ silc_schedule_task_add_timeout(server->schedule, silc_server_do_rekey,
+ sock, idata->sconn->rekey_timeout, 0);
}
-SILC_TASK_CALLBACK(silc_server_close_connection_final)
+/* Rekey callback. Start rekey as initiator */
+
+SILC_TASK_CALLBACK(silc_server_do_rekey)
{
SilcServer server = app_context;
- SilcSocketConnection sock = context;
+ SilcPacketStream sock = context;
+ SilcIDListData idata = silc_packet_get_context(sock);
+ SilcSKE ske;
- SILC_LOG_DEBUG(("Deleting socket %p", sock));
+ /* Do not execute rekey with disabled connections */
+ if (idata->status & SILC_IDLIST_STATUS_DISABLED)
+ return;
- /* Close the actual connection */
- silc_net_close_connection(sock->sock);
- server->sockets[sock->sock] = NULL;
- server->stat.conn_num--;
+ /* If another protocol is active do not start rekey */
+ if (idata->sconn->op) {
+ SILC_LOG_DEBUG(("Waiting for other protocol to finish before rekeying"));
+ silc_schedule_task_add_timeout(server->schedule, silc_server_do_rekey,
+ sock, 60, 0);
+ return;
+ }
+
+ SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s]",
+ idata->sconn->remote_host, idata->sconn->remote_port,
+ SILC_CONNTYPE_STRING(idata->conn_type)));
+
+ /* Allocate SKE */
+ ske = silc_ske_alloc(server->rng, server->schedule, server->repository,
+ server->public_key, server->private_key, sock);
+ if (!ske)
+ return;
+
+ /* Set SKE callbacks */
+ silc_ske_set_callbacks(ske, NULL, silc_server_rekey_completion, sock);
- /* We won't listen for this connection anymore */
- silc_schedule_task_del_by_fd(server->schedule, sock->sock);
- silc_schedule_unset_listen_fd(server->schedule, sock->sock);
+ /* Perform rekey */
+ idata->sconn->op = silc_ske_rekey_initiator(ske, sock, idata->rekey);
+}
+
+
+/****************************** Disconnection *******************************/
+
+/* Destroys packet stream. */
- silc_socket_free(sock);
+SILC_TASK_CALLBACK(silc_server_close_connection_final)
+{
+ silc_packet_stream_destroy(context);
}
/* Closes connection to socket connection */
void silc_server_close_connection(SilcServer server,
- SilcSocketConnection sock)
+ SilcPacketStream sock)
{
+ SilcIDListData idata = silc_packet_get_context(sock);
char tmp[128];
+ const char *hostname;
+ SilcUInt16 port;
- if (SILC_IS_DISCONNECTED(sock)) {
- silc_schedule_task_del_by_fd(server->schedule, sock->sock);
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_close_connection_final,
- (void *)sock, 0, 1, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- server->sockets[sock->sock] = NULL;
- return;
- }
-
+#if 0
/* If any protocol is active cancel its execution. It will call
the final callback which will finalize the disconnection. */
if (sock->protocol && sock->protocol->protocol &&
sock->protocol = NULL;
return;
}
+#endif
memset(tmp, 0, sizeof(tmp));
- silc_socket_get_error(sock, tmp, sizeof(tmp));
- SILC_LOG_INFO(("Closing connection %s:%d [%s] %s", sock->hostname,
- sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router"), tmp[0] ? tmp : ""));
-
- SILC_SET_DISCONNECTED(sock);
- silc_socket_set_qos(sock, 0, 0, 0, 0, NULL);
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_close_connection_final,
- (void *)sock, 0, 1, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- server->sockets[sock->sock] = NULL;
+ // silc_socket_get_error(sock, tmp, sizeof(tmp));
+ silc_socket_stream_get_info(sock, NULL, &hostname, NULL, &port);
+ SILC_LOG_INFO(("Closing connection %s:%d [%s] %s", hostname, port,
+ SILC_CONNTYPE_STRING(idata->conn_type),
+ tmp[0] ? tmp : ""));
+
+ // silc_socket_set_qos(sock, 0, 0, 0, 0, NULL);
+
+ /* Close connection with timeout */
+ server->stat.conn_num--;
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_close_connection_final,
+ sock, 0, 1);
}
/* Sends disconnect message to remote connection and disconnects the
- connection. NOTE: If this is called from protocol callback
- then sock->protocol must be set NULL before calling this, since
- this routine dispatches protocol callbacks too. */
+ connection. */
void silc_server_disconnect_remote(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcStatus status, ...)
{
- va_list ap;
unsigned char buf[512];
- SilcBuffer buffer;
+ va_list ap;
char *cp;
- int len;
if (!sock)
return;
- if (SILC_IS_DISCONNECTING(sock)) {
- SILC_SET_DISCONNECTED(sock);
- silc_server_close_connection(server, sock);
- return;
- }
+ SILC_LOG_DEBUG(("Disconnecting remote host"));
- memset(buf, 0, sizeof(buf));
va_start(ap, status);
cp = va_arg(ap, char *);
- if (cp) {
- vsnprintf(buf, sizeof(buf) - 1, cp, ap);
- cp = buf;
- }
- va_end(ap);
-
- SILC_LOG_DEBUG(("Disconnecting remote host"));
-
- /* Notify remote end that the conversation is over. The notify message
- is tried to be sent immediately. */
-
- len = 1;
- if (cp)
- len += silc_utf8_encoded_len(buf, strlen(buf), SILC_STRING_ASCII);
-
- buffer = silc_buffer_alloc_size(len);
- if (!buffer)
- goto out;
-
- buffer->data[0] = status;
if (cp)
- silc_utf8_encode(buf, strlen(buf), SILC_STRING_ASCII, buffer->data + 1,
- buffer->len - 1);
- silc_server_packet_send(server, sock, SILC_PACKET_DISCONNECT, 0,
- buffer->data, buffer->len, TRUE);
- silc_buffer_free(buffer);
+ silc_vsnprintf(buf, sizeof(buf), cp, ap);
+ va_end(ap);
- out:
- silc_server_packet_queue_purge(server, sock);
+ /* Send SILC_PACKET_DISCONNECT */
+ silc_packet_send_va(sock, SILC_PACKET_DISCONNECT, 0,
+ SILC_STR_UI_CHAR(status),
+ SILC_STR_UI8_STRING(cp ? buf : NULL),
+ SILC_STR_END);
- /* Mark the connection to be disconnected */
- SILC_SET_DISCONNECTING(sock);
+ /* Close connection */
silc_server_close_connection(server, sock);
}
SILC_TASK_CALLBACK(silc_server_free_client_data_timeout)
{
- SilcServer server = app_context;
SilcClientEntry client = context;
assert(!silc_hash_table_count(client->channels));
silc_idlist_del_data(client);
- silc_idcache_purge_by_context(server->local_list->clients, client);
+ // silc_idcache_purge_by_context(server->local_list->clients, client);
}
/* Frees client data and notifies about client's signoff. */
void silc_server_free_client_data(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcClientEntry client,
int notify,
const char *signoff)
{
SILC_LOG_DEBUG(("Freeing client data"));
- /* If there is pending outgoing data for the client then purge it
- to the network before removing the client entry. */
- silc_server_packet_queue_purge(server, sock);
-
if (client->id) {
/* Check if anyone is watching this nickname */
if (server->server_type == SILC_ROUTER)
into history (for WHOWAS command) for 5 minutes, unless we're
shutting down server. */
if (!server->server_shutdown) {
- silc_schedule_task_add(server->schedule, 0,
- silc_server_free_client_data_timeout,
- client, 600, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_free_client_data_timeout,
+ client, 600, 0);
client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
client->mode = 0;
entities. */
void silc_server_free_sock_user_data(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
const char *signoff_message)
{
+ SilcIDListData idata = silc_packet_get_context(sock);
- /* If any protocol is active cancel its execution */
- if (sock->protocol && sock->protocol->protocol &&
- sock->protocol->protocol->type != SILC_PROTOCOL_SERVER_BACKUP) {
- SILC_LOG_DEBUG(("Cancelling protocol, calling final callback"));
- silc_protocol_cancel(sock->protocol, server->schedule);
- sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute_final(sock->protocol, server->schedule);
- sock->protocol = NULL;
- if (!sock->user_data)
- return;
- }
+ if (!idata)
+ return;
- switch (sock->type) {
- case SILC_SOCKET_TYPE_CLIENT:
+ switch (idata->conn_type) {
+ case SILC_CONN_CLIENT:
{
- SilcClientEntry user_data = (SilcClientEntry)sock->user_data;
- silc_server_free_client_data(server, sock, user_data, TRUE,
+ SilcClientEntry client_entry = (SilcClientEntry)idata;
+ silc_server_free_client_data(server, sock, client_entry, TRUE,
signoff_message);
break;
}
- case SILC_SOCKET_TYPE_SERVER:
- case SILC_SOCKET_TYPE_ROUTER:
+
+ case SILC_CONN_SERVER:
+ case SILC_CONN_ROUTER:
{
- SilcServerEntry user_data = (SilcServerEntry)sock->user_data;
+ SilcServerEntry user_data = (SilcServerEntry)idata;
SilcServerEntry backup_router = NULL;
SILC_LOG_DEBUG(("Freeing server data"));
if (!server->backup_router && server->server_type == SILC_ROUTER &&
backup_router == server->id_entry &&
- sock->type != SILC_SOCKET_TYPE_ROUTER)
+ idata->conn_type != SILC_CONN_ROUTER)
backup_router = NULL;
if (server->server_shutdown || server->backup_noswitch)
/* We stop here to take a breath */
sleep(2);
+#if 0
if (server->backup_router) {
server->server_type = SILC_ROUTER;
silc_server_backup_connected,
NULL);
}
+#endif /* 0 */
/* Mark this connection as replaced */
silc_server_backup_replaced_add(server, user_data->id,
silc_server_backup_replaced_add(server, user_data->id,
backup_router);
} else if (server->server_type == SILC_SERVER &&
- sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ idata->conn_type == SILC_CONN_ROUTER) {
/* Reconnect to the router (backup) */
if (!server->no_reconnect)
silc_server_create_connections(server);
coming from the primary router, so mark that as the owner
of this entry. */
if (server->server_type == SILC_BACKUP_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_SERVER)
+ sock->type == SILC_CONN_SERVER)
silc_server_remove_clients_by_server(server, server->router,
user_data, TRUE);
else
silc_idlist_del_data(user_data);
if (!silc_idlist_del_server(server->local_list, user_data))
silc_idlist_del_server(server->global_list, user_data);
- if (sock->type == SILC_SOCKET_TYPE_SERVER) {
+ if (idata->conn_type == SILC_CONN_SERVER) {
server->stat.my_servers--;
server->stat.servers--;
} else {
}
break;
}
+
default:
{
- SilcUnknownEntry user_data = (SilcUnknownEntry)sock->user_data;
+ SilcUnknownEntry entry = (SilcUnknownEntry)idata;
SILC_LOG_DEBUG(("Freeing unknown connection data"));
- silc_idlist_del_data(user_data);
- silc_free(user_data);
+ silc_idlist_del_data(idata);
+ silc_free(entry);
break;
}
}
-
- sock->user_data = NULL;
}
/* Removes client from all channels it has joined. This is used when client
channel is removed as well. This sends the SIGNOFF notify types. */
void silc_server_remove_from_channels(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcClientEntry client,
- bool notify,
+ SilcBool notify,
const char *signoff_message,
- bool keygen,
- bool killed)
+ SilcBool keygen,
+ SilcBool killed)
{
SilcChannelEntry channel;
SilcChannelClientEntry chl;
silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
SILC_NOTIFY_TYPE_SIGNOFF,
signoff_message ? 2 : 1,
- clidp->data, clidp->len,
+ clidp->data, silc_buffer_len(clidp),
signoff_message, signoff_message ?
strlen(signoff_message) : 0);
silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
SILC_NOTIFY_TYPE_SIGNOFF,
signoff_message ? 2 : 1,
- clidp->data, clidp->len,
+ clidp->data, silc_buffer_len(clidp),
signoff_message, signoff_message ?
strlen(signoff_message) : 0);
SilcBuffer ab;
SilcArgumentPayload iargs;
ab = silc_argument_payload_encode_one(NULL, clidp->data,
- clidp->len, 3);
- iargs = silc_argument_payload_parse(ab->data, ab->len, 1);
+ silc_buffer_len(clidp), 3);
+ iargs = silc_argument_payload_parse(ab->data, silc_buffer_len(ab), 1);
silc_server_inviteban_process(server, channel->invite_list, 1, iargs);
silc_buffer_free(ab);
silc_argument_payload_free(iargs);
last client leaves the channel. If `notify' is FALSE notify messages
are not sent. */
-bool silc_server_remove_from_one_channel(SilcServer server,
- SilcSocketConnection sock,
+SilcBool silc_server_remove_from_one_channel(SilcServer server,
+ SilcPacketStream sock,
SilcChannelEntry channel,
SilcClientEntry client,
- bool notify)
+ SilcBool notify)
{
SilcChannelClientEntry chl;
SilcBuffer clidp;
if (notify && channel->global_users)
silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
SILC_NOTIFY_TYPE_LEAVE, 1,
- clidp->data, clidp->len);
+ clidp->data, silc_buffer_len(clidp));
silc_schedule_task_del_by_context(server->schedule, channel->rekey);
silc_server_channel_delete(server, channel);
if (notify)
silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
SILC_NOTIFY_TYPE_LEAVE, 1,
- clidp->data, clidp->len);
+ clidp->data, silc_buffer_len(clidp));
silc_buffer_free(clidp);
return TRUE;
}
+#if 0
/* Timeout callback. This is called if connection is idle or for some
other reason is not responding within some period of time. This
disconnects the remote end. */
SILC_TASK_CALLBACK(silc_server_timeout_remote)
{
SilcServer server = (SilcServer)context;
- SilcSocketConnection sock = server->sockets[fd];
- SilcProtocolType protocol = 0;
+ SilcPacketStream sock = server->sockets[fd];
SILC_LOG_DEBUG(("Start"));
if (sock->user_data)
silc_server_free_sock_user_data(server, sock, NULL);
}
+#endif /* 0 */
/* Creates new channel. Sends NEW_CHANNEL packet to primary route. This
function may be used only by router. In real SILC network all channels
{
SilcChannelID *channel_id;
SilcChannelEntry entry;
- SilcCipher key;
+ SilcCipher send_key, receive_key;
SilcHmac newhmac;
SILC_LOG_DEBUG(("Creating new channel %s", channel_name));
hmac = SILC_DEFAULT_HMAC;
/* Allocate cipher */
- if (!silc_cipher_alloc(cipher, &key))
+ if (!silc_cipher_alloc(cipher, &send_key))
return NULL;
+ if (!silc_cipher_alloc(cipher, &receive_key)) {
+ silc_cipher_free(send_key);
+ return NULL;
+ }
/* Allocate hmac */
if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
- silc_cipher_free(key);
+ silc_cipher_free(send_key);
+ silc_cipher_free(receive_key);
return NULL;
}
if (!silc_id_create_channel_id(server, router_id, server->rng,
&channel_id)) {
silc_free(channel_name);
- silc_cipher_free(key);
+ silc_cipher_free(send_key);
+ silc_cipher_free(receive_key);
silc_hmac_free(newhmac);
return NULL;
}
/* Create the channel */
entry = silc_idlist_add_channel(server->local_list, channel_name,
SILC_CHANNEL_MODE_NONE, channel_id,
- NULL, key, newhmac, 0);
+ NULL, send_key, receive_key, newhmac);
if (!entry) {
silc_free(channel_name);
- silc_cipher_free(key);
+ silc_cipher_free(send_key);
+ silc_cipher_free(receive_key);
silc_hmac_free(newhmac);
silc_free(channel_id);
return NULL;
/* Now create the actual key material */
if (!silc_server_create_channel_key(server, entry,
- silc_cipher_get_key_len(key) / 8)) {
+ silc_cipher_get_key_len(send_key) / 8)) {
silc_idlist_del_channel(server->local_list, entry);
return NULL;
}
/* Distribute to backup routers */
if (broadcast && server->server_type == SILC_ROUTER) {
SilcBuffer packet;
- unsigned char *cid;
+ unsigned char cid[32];
SilcUInt32 name_len = strlen(channel_name);
- SilcUInt32 channel_id_len = silc_id_get_len(entry->id, SILC_ID_CHANNEL);
- cid = silc_id_id2str(entry->id, SILC_ID_CHANNEL);
+ SilcUInt32 id_len;
+ silc_id_id2str(entry->id, SILC_ID_CHANNEL, cid, sizeof(cid), &id_len);
packet = silc_channel_payload_encode(channel_name, name_len,
- cid, channel_id_len, entry->mode);
+ cid, id_len, entry->mode);
silc_server_backup_send(server, NULL, SILC_PACKET_NEW_CHANNEL, 0,
- packet->data, packet->len, FALSE, TRUE);
- silc_free(cid);
+ packet->data, silc_buffer_len(packet), FALSE,
+ TRUE);
silc_buffer_free(packet);
}
int broadcast)
{
SilcChannelEntry entry;
- SilcCipher key;
+ SilcCipher send_key, receive_key;
SilcHmac newhmac;
SILC_LOG_DEBUG(("Creating new channel %s", channel_name));
hmac = SILC_DEFAULT_HMAC;
/* Allocate cipher */
- if (!silc_cipher_alloc(cipher, &key))
+ if (!silc_cipher_alloc(cipher, &send_key))
return NULL;
+ if (!silc_cipher_alloc(cipher, &receive_key)) {
+ silc_cipher_free(send_key);
+ return NULL;
+ }
/* Allocate hmac */
if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
- silc_cipher_free(key);
+ silc_cipher_free(send_key);
+ silc_cipher_free(receive_key);
return NULL;
}
/* Create the channel */
entry = silc_idlist_add_channel(server->local_list, channel_name,
SILC_CHANNEL_MODE_NONE, channel_id,
- NULL, key, newhmac, 0);
+ NULL, send_key, receive_key, newhmac);
if (!entry) {
- silc_cipher_free(key);
+ silc_cipher_free(send_key);
+ silc_cipher_free(receive_key);
silc_hmac_free(newhmac);
silc_free(channel_name);
return NULL;
/* Now create the actual key material */
if (!silc_server_create_channel_key(server, entry,
- silc_cipher_get_key_len(key) / 8)) {
+ silc_cipher_get_key_len(send_key) / 8)) {
silc_idlist_del_channel(server->local_list, entry);
return NULL;
}
/* Distribute to backup routers */
if (broadcast && server->server_type == SILC_ROUTER) {
SilcBuffer packet;
- unsigned char *cid;
+ unsigned char cid[32];
SilcUInt32 name_len = strlen(channel_name);
- SilcUInt32 channel_id_len = silc_id_get_len(entry->id, SILC_ID_CHANNEL);
- cid = silc_id_id2str(entry->id, SILC_ID_CHANNEL);
+ SilcUInt32 id_len;
+ silc_id_id2str(entry->id, SILC_ID_CHANNEL, cid, sizeof(cid), &id_len);
packet = silc_channel_payload_encode(channel_name, name_len,
- cid, channel_id_len, entry->mode);
+ cid, id_len, entry->mode);
silc_server_backup_send(server, NULL, SILC_PACKET_NEW_CHANNEL, 0,
- packet->data, packet->len, FALSE, TRUE);
- silc_free(cid);
+ packet->data, silc_buffer_len(packet), FALSE,
+ TRUE);
silc_buffer_free(packet);
}
but also to re-generate new key for channel. If `key_len' is provided
it is the bytes of the key length. */
-bool silc_server_create_channel_key(SilcServer server,
- SilcChannelEntry channel,
- SilcUInt32 key_len)
+SilcBool silc_server_create_channel_key(SilcServer server,
+ SilcChannelEntry channel,
+ SilcUInt32 key_len)
{
int i;
unsigned char channel_key[32], hash[SILC_HASH_MAXLEN];
SILC_LOG_DEBUG(("Generating channel %s key", channel->channel_name));
- if (!channel->channel_key)
- if (!silc_cipher_alloc(SILC_DEFAULT_CIPHER, &channel->channel_key)) {
- channel->channel_key = NULL;
+ if (!channel->send_key)
+ if (!silc_cipher_alloc(SILC_DEFAULT_CIPHER, &channel->send_key)) {
+ channel->send_key = NULL;
+ return FALSE;
+ }
+ if (!channel->receive_key)
+ if (!silc_cipher_alloc(SILC_DEFAULT_CIPHER, &channel->receive_key)) {
+ silc_cipher_free(channel->send_key);
+ channel->send_key = channel->receive_key = NULL;
return FALSE;
}
else if (channel->key_len)
len = channel->key_len / 8;
else
- len = silc_cipher_get_key_len(channel->channel_key) / 8;
+ len = silc_cipher_get_key_len(channel->send_key) / 8;
/* Create channel key */
for (i = 0; i < len; i++) channel_key[i] = silc_rng_get_byte(server->rng);
/* Set the key */
- silc_cipher_set_key(channel->channel_key, channel_key, len * 8);
+ silc_cipher_set_key(channel->send_key, channel_key, len * 8, TRUE);
+ silc_cipher_set_key(channel->receive_key, channel_key, len * 8, FALSE);
/* Remove old key if exists */
if (channel->key) {
if (!silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac)) {
memset(channel->key, 0, channel->key_len / 8);
silc_free(channel->key);
- channel->channel_key = NULL;
+ silc_cipher_free(channel->send_key);
+ silc_cipher_free(channel->receive_key);
+ channel->send_key = channel->receive_key = NULL;
return FALSE;
}
silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, len, hash);
silc_schedule_task_del(server->schedule, channel->rekey->task);
channel->rekey->task =
- silc_schedule_task_add(server->schedule, 0,
- silc_server_channel_key_rekey,
- (void *)channel->rekey,
- server->config->channel_rekey_secs, 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_channel_key_rekey,
+ (void *)channel->rekey,
+ server->config->channel_rekey_secs, 0);
}
return TRUE;
SilcChannelEntry channel)
{
SilcChannelKeyPayload payload = NULL;
- SilcChannelID *id = NULL;
+ SilcChannelID id;
unsigned char *tmp, hash[SILC_HASH_MAXLEN];
SilcUInt32 tmp_len;
char *cipher;
/* Decode channel key payload */
payload = silc_channel_key_payload_parse(key_payload->data,
- key_payload->len);
+ silc_buffer_len(key_payload));
if (!payload) {
SILC_LOG_ERROR(("Bad channel key payload received, dropped"));
channel = NULL;
/* Get channel ID */
tmp = silc_channel_key_get_id(payload, &tmp_len);
- id = silc_id_str2id(tmp, tmp_len, SILC_ID_CHANNEL);
- if (!id) {
+ if (!silc_id_str2id(tmp, tmp_len, SILC_ID_CHANNEL, &id, sizeof(id))) {
channel = NULL;
goto out;
}
- channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
+ channel = silc_idlist_find_channel_by_id(server->local_list, &id, NULL);
if (!channel) {
- channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
+ channel = silc_idlist_find_channel_by_id(server->global_list, &id, NULL);
if (!channel) {
if (server->server_type == SILC_ROUTER)
SILC_LOG_ERROR(("Received key for non-existent channel %s",
- silc_id_render(id, SILC_ID_CHANNEL)));
+ silc_id_render(&id, SILC_ID_CHANNEL)));
goto out;
}
}
if (channel->key) {
memset(channel->key, 0, channel->key_len / 8);
silc_free(channel->key);
- silc_cipher_free(channel->channel_key);
+ silc_cipher_free(channel->send_key);
+ silc_cipher_free(channel->receive_key);
}
/* Create new cipher */
- if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
- channel->channel_key = NULL;
+ if (!silc_cipher_alloc(cipher, &channel->send_key)) {
+ channel->send_key = NULL;
+ channel = NULL;
+ goto out;
+ }
+ if (!silc_cipher_alloc(cipher, &channel->receive_key)) {
+ silc_cipher_free(channel->send_key);
+ channel->send_key = channel->receive_key = NULL;
channel = NULL;
goto out;
}
/* Save the key */
channel->key_len = tmp_len * 8;
channel->key = silc_memdup(tmp, tmp_len);
- silc_cipher_set_key(channel->channel_key, tmp, channel->key_len);
+ silc_cipher_set_key(channel->send_key, tmp, channel->key_len, TRUE);
+ silc_cipher_set_key(channel->receive_key, tmp, channel->key_len, FALSE);
/* Generate HMAC key from the channel key data and set it */
if (!channel->hmac)
if (!silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac)) {
memset(channel->key, 0, channel->key_len / 8);
silc_free(channel->key);
- channel->channel_key = NULL;
+ silc_cipher_free(channel->send_key);
+ silc_cipher_free(channel->receive_key);
+ channel->send_key = channel->receive_key = NULL;
return FALSE;
}
silc_hash_make(silc_hmac_get_hash(channel->hmac), tmp, tmp_len, hash);
silc_schedule_task_del(server->schedule, channel->rekey->task);
channel->rekey->task =
- silc_schedule_task_add(server->schedule, 0,
- silc_server_channel_key_rekey,
- (void *)channel->rekey,
- server->config->channel_rekey_secs, 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_channel_key_rekey,
+ (void *)channel->rekey,
+ server->config->channel_rekey_secs, 0);
}
out:
- silc_free(id);
if (payload)
silc_channel_key_payload_free(payload);
return channel;
}
-/* Heartbeat callback. This function is set as argument for the
- silc_socket_set_heartbeat function. The library will call this function
- at the set time interval. */
-
-void silc_server_perform_heartbeat(SilcSocketConnection sock,
- void *hb_context)
-{
- SilcServer server = hb_context;
-
- SILC_LOG_DEBUG(("Sending heartbeat to %s:%d (%s)", sock->hostname,
- sock->port, sock->ip));
-
- /* Send the heartbeat */
- silc_server_send_heartbeat(server, sock);
-}
-
/* Returns assembled of all servers in the given ID list. The packet's
form is dictated by the New ID payload. */
SilcBuffer *servers,
unsigned long creation_time)
{
- SilcIDCacheList list;
+ SilcList list;
SilcIDCacheEntry id_cache;
SilcServerEntry entry;
SilcBuffer idp;
/* Go through all clients in the list */
if (silc_idcache_get_all(id_list->servers, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- entry = (SilcServerEntry)id_cache->context;
-
- /* Do not announce the one we've sending our announcements and
- do not announce ourself. Also check the creation time if it's
- provided. */
- if ((entry == remote) || (entry == server->id_entry) ||
- (creation_time && entry->data.created < creation_time)) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- continue;
- }
-
- idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
-
- *servers = silc_buffer_realloc(*servers,
- (*servers ?
- (*servers)->truelen + idp->len :
- idp->len));
- silc_buffer_pull_tail(*servers, ((*servers)->end - (*servers)->data));
- silc_buffer_put(*servers, idp->data, idp->len);
- silc_buffer_pull(*servers, idp->len);
- silc_buffer_free(idp);
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ entry = (SilcServerEntry)id_cache->context;
+
+ /* Do not announce the one we've sending our announcements and
+ do not announce ourself. Also check the creation time if it's
+ provided. */
+ if ((entry == remote) || (entry == server->id_entry) ||
+ (creation_time && entry->data.created < creation_time))
+ continue;
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- }
+ idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
+
+ *servers = silc_buffer_realloc(*servers,
+ (*servers ?
+ silc_buffer_truelen((*servers)) +
+ silc_buffer_len(idp) :
+ silc_buffer_len(idp)));
+ silc_buffer_pull_tail(*servers, ((*servers)->end - (*servers)->data));
+ silc_buffer_put(*servers, idp->data, silc_buffer_len(idp));
+ silc_buffer_pull(*servers, silc_buffer_len(idp));
+ silc_buffer_free(idp);
}
-
- silc_idcache_list_free(list);
}
}
then only the servers that has been created after the `creation_time'
will be announced. */
-void silc_server_announce_servers(SilcServer server, bool global,
+void silc_server_announce_servers(SilcServer server, SilcBool global,
unsigned long creation_time,
- SilcSocketConnection remote)
+ SilcPacketStream remote)
{
SilcBuffer servers = NULL;
SILC_LOG_DEBUG(("Announcing servers"));
/* Get servers in local list */
- silc_server_announce_get_servers(server, remote->user_data,
+ silc_server_announce_get_servers(server, silc_packet_get_context(remote),
server->local_list, &servers,
creation_time);
if (global)
/* Get servers in global list */
- silc_server_announce_get_servers(server, remote->user_data,
+ silc_server_announce_get_servers(server, silc_packet_get_context(remote),
server->global_list, &servers,
creation_time);
if (servers) {
silc_buffer_push(servers, servers->data - servers->head);
- SILC_LOG_HEXDUMP(("servers"), servers->data, servers->len);
+ SILC_LOG_HEXDUMP(("servers"), servers->data, silc_buffer_len(servers));
/* Send the packet */
silc_server_packet_send(server, remote,
SILC_PACKET_NEW_ID, SILC_PACKET_FLAG_LIST,
- servers->data, servers->len, TRUE);
+ servers->data, silc_buffer_len(servers));
silc_buffer_free(servers);
}
SilcBuffer *umodes,
unsigned long creation_time)
{
- SilcIDCacheList list;
+ SilcList list;
SilcIDCacheEntry id_cache;
SilcClientEntry client;
SilcBuffer idp;
/* Go through all clients in the list */
if (silc_idcache_get_all(id_list->clients, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- client = (SilcClientEntry)id_cache->context;
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ client = (SilcClientEntry)id_cache->context;
- if (creation_time && client->data.created < creation_time) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- continue;
- }
- if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- continue;
- }
- if (!client->connection && !client->router) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- continue;
- }
+ if (creation_time && client->data.created < creation_time)
+ continue;
+ if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED))
+ continue;
+ if (!client->connection && !client->router)
+ continue;
- idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
-
- *clients = silc_buffer_realloc(*clients,
- (*clients ?
- (*clients)->truelen + idp->len :
- idp->len));
- silc_buffer_pull_tail(*clients, ((*clients)->end - (*clients)->data));
- silc_buffer_put(*clients, idp->data, idp->len);
- silc_buffer_pull(*clients, idp->len);
-
- SILC_PUT32_MSB(client->mode, mode);
- tmp =
- silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_UMODE_CHANGE,
- 2, idp->data, idp->len,
- mode, 4);
- *umodes = silc_buffer_realloc(*umodes,
- (*umodes ?
- (*umodes)->truelen + tmp->len :
- tmp->len));
- silc_buffer_pull_tail(*umodes, ((*umodes)->end - (*umodes)->data));
- silc_buffer_put(*umodes, tmp->data, tmp->len);
- silc_buffer_pull(*umodes, tmp->len);
- silc_buffer_free(tmp);
-
- silc_buffer_free(idp);
-
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- }
+ idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+
+ *clients = silc_buffer_realloc(*clients,
+ (*clients ?
+ silc_buffer_truelen((*clients)) +
+ silc_buffer_len(idp) :
+ silc_buffer_len(idp)));
+ silc_buffer_pull_tail(*clients, ((*clients)->end - (*clients)->data));
+ silc_buffer_put(*clients, idp->data, silc_buffer_len(idp));
+ silc_buffer_pull(*clients, silc_buffer_len(idp));
+
+ SILC_PUT32_MSB(client->mode, mode);
+ tmp =
+ silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_UMODE_CHANGE,
+ 2, idp->data, silc_buffer_len(idp),
+ mode, 4);
+ *umodes = silc_buffer_realloc(*umodes,
+ (*umodes ?
+ silc_buffer_truelen((*umodes)) +
+ silc_buffer_len(tmp) :
+ silc_buffer_len(tmp)));
+ silc_buffer_pull_tail(*umodes, ((*umodes)->end - (*umodes)->data));
+ silc_buffer_put(*umodes, tmp->data, silc_buffer_len(tmp));
+ silc_buffer_pull(*umodes, silc_buffer_len(tmp));
+ silc_buffer_free(tmp);
+
+ silc_buffer_free(idp);
}
-
- silc_idcache_list_free(list);
}
}
void silc_server_announce_clients(SilcServer server,
unsigned long creation_time,
- SilcSocketConnection remote)
+ SilcPacketStream remote)
{
SilcBuffer clients = NULL;
SilcBuffer umodes = NULL;
if (clients) {
silc_buffer_push(clients, clients->data - clients->head);
- SILC_LOG_HEXDUMP(("clients"), clients->data, clients->len);
+ SILC_LOG_HEXDUMP(("clients"), clients->data, silc_buffer_len(clients));
/* Send the packet */
silc_server_packet_send(server, remote,
SILC_PACKET_NEW_ID, SILC_PACKET_FLAG_LIST,
- clients->data, clients->len, TRUE);
+ clients->data, silc_buffer_len(clients));
silc_buffer_free(clients);
}
if (umodes) {
silc_buffer_push(umodes, umodes->data - umodes->head);
- SILC_LOG_HEXDUMP(("umodes"), umodes->data, umodes->len);
+ SILC_LOG_HEXDUMP(("umodes"), umodes->data, silc_buffer_len(umodes));
/* Send the packet */
silc_server_packet_send(server, remote,
SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
- umodes->data, umodes->len, TRUE);
+ umodes->data, silc_buffer_len(umodes));
silc_buffer_free(umodes);
}
if (channel->topic) {
chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
*topic = silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_TOPIC_SET, 2,
- chidp->data, chidp->len,
+ chidp->data,
+ silc_buffer_len(chidp),
channel->topic,
strlen(channel->topic));
silc_buffer_free(chidp);
SILC_PUT16_MSB(type, list->data);
silc_hash_table_list(channel->invite_list, &htl);
while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
- list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
+ list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2),
type);
silc_hash_table_list_reset(&htl);
idp2 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
*invite =
silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_INVITE, 5,
- idp->data, idp->len,
+ idp->data, silc_buffer_len(idp),
channel->channel_name,
strlen(channel->channel_name),
- idp2->data, idp2->len,
+ idp2->data, silc_buffer_len(idp2),
a, 1,
- list->data, list->len);
+ list->data, silc_buffer_len(list));
silc_buffer_free(idp2);
silc_buffer_free(list);
}
SILC_PUT16_MSB(type, list->data);
silc_hash_table_list(channel->ban_list, &htl);
while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
- list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
+ list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2),
type);
silc_hash_table_list_reset(&htl);
*ban =
silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_BAN, 3,
- idp->data, idp->len,
+ idp->data, silc_buffer_len(idp),
a, 1,
- list->data, list->len);
+ list->data, silc_buffer_len(list));
silc_buffer_free(list);
}
SILC_PUT32_MSB(channel->user_limit, ulimit);
hmac = channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) : NULL;
if (channel->founder_key)
- fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
+ fkey = silc_public_key_payload_encode(channel->founder_key);
tmp =
silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_CMODE_CHANGE,
- 8, csidp->data, csidp->len,
+ 8, csidp->data,
+ silc_buffer_len(csidp),
mode, sizeof(mode),
NULL, 0,
hmac, hmac ? strlen(hmac) : 0,
channel->passphrase ?
strlen(channel->passphrase) : 0,
fkey ? fkey->data : NULL,
- fkey ? fkey->len : 0,
+ fkey ? silc_buffer_len(fkey) : 0,
chpklist ? chpklist->data : NULL,
- chpklist ? chpklist->len : 0,
+ chpklist ?
+ silc_buffer_len(chpklist) : 0,
(channel->mode &
SILC_CHANNEL_MODE_ULIMIT ?
ulimit : NULL),
(channel->mode &
SILC_CHANNEL_MODE_ULIMIT ?
sizeof(ulimit) : 0));
- len = tmp->len;
+ len = silc_buffer_len(tmp);
*channel_modes =
silc_buffer_realloc(*channel_modes,
(*channel_modes ?
- (*channel_modes)->truelen + len : len));
+ silc_buffer_truelen((*channel_modes)) + len : len));
silc_buffer_pull_tail(*channel_modes,
((*channel_modes)->end -
(*channel_modes)->data));
- silc_buffer_put(*channel_modes, tmp->data, tmp->len);
+ silc_buffer_put(*channel_modes, tmp->data, silc_buffer_len(tmp));
silc_buffer_pull(*channel_modes, len);
silc_buffer_free(tmp);
silc_buffer_free(fkey);
/* JOIN Notify */
tmp = silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_JOIN, 2,
- clidp->data, clidp->len,
- chidp->data, chidp->len);
- len = tmp->len;
+ clidp->data,
+ silc_buffer_len(clidp),
+ chidp->data,
+ silc_buffer_len(chidp));
+ len = silc_buffer_len(tmp);
*channel_users =
silc_buffer_realloc(*channel_users,
(*channel_users ?
- (*channel_users)->truelen + len : len));
+ silc_buffer_truelen((*channel_users)) + len : len));
silc_buffer_pull_tail(*channel_users,
((*channel_users)->end -
(*channel_users)->data));
- silc_buffer_put(*channel_users, tmp->data, tmp->len);
+ silc_buffer_put(*channel_users, tmp->data, silc_buffer_len(tmp));
silc_buffer_pull(*channel_users, len);
silc_buffer_free(tmp);
/* CUMODE notify for mode change on the channel */
SILC_PUT32_MSB(chl->mode, mode);
if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && channel->founder_key)
- fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
+ fkey = silc_public_key_payload_encode(channel->founder_key);
tmp = silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_CUMODE_CHANGE,
- 4, csidp->data, csidp->len,
+ 4, csidp->data,
+ silc_buffer_len(csidp),
mode, sizeof(mode),
- clidp->data, clidp->len,
+ clidp->data,
+ silc_buffer_len(clidp),
fkey ? fkey->data : NULL,
- fkey ? fkey->len : 0);
- len = tmp->len;
+ fkey ? silc_buffer_len(fkey) : 0);
+ len = silc_buffer_len(tmp);
*channel_users_modes =
silc_buffer_realloc(*channel_users_modes,
(*channel_users_modes ?
- (*channel_users_modes)->truelen + len : len));
+ silc_buffer_truelen((*channel_users_modes)) +
+ len : len));
silc_buffer_pull_tail(*channel_users_modes,
((*channel_users_modes)->end -
(*channel_users_modes)->data));
- silc_buffer_put(*channel_users_modes, tmp->data, tmp->len);
+ silc_buffer_put(*channel_users_modes, tmp->data, silc_buffer_len(tmp));
silc_buffer_pull(*channel_users_modes, len);
silc_buffer_free(tmp);
silc_buffer_free(fkey);
SilcChannelID ***channel_ids,
unsigned long creation_time)
{
- SilcIDCacheList list;
+ SilcList list;
SilcIDCacheEntry id_cache;
SilcChannelEntry channel;
- unsigned char *cid;
+ unsigned char cid[32];
SilcUInt32 id_len;
SilcUInt16 name_len;
int len;
int i = *channel_users_modes_c;
- bool announce;
+ SilcBool announce;
SILC_LOG_DEBUG(("Start"));
/* Go through all channels in the list */
if (silc_idcache_get_all(id_list->channels, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- channel = (SilcChannelEntry)id_cache->context;
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ channel = (SilcChannelEntry)id_cache->context;
- if (creation_time && channel->created < creation_time)
- announce = FALSE;
- else
- announce = TRUE;
-
- cid = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
- name_len = strlen(channel->channel_name);
-
- if (announce) {
- len = 4 + name_len + id_len + 4;
- *channels =
- silc_buffer_realloc(*channels,
- (*channels ? (*channels)->truelen +
- len : len));
- silc_buffer_pull_tail(*channels,
- ((*channels)->end - (*channels)->data));
- silc_buffer_format(*channels,
- SILC_STR_UI_SHORT(name_len),
- SILC_STR_UI_XNSTRING(channel->channel_name,
- name_len),
- SILC_STR_UI_SHORT(id_len),
+ if (creation_time && channel->created < creation_time)
+ announce = FALSE;
+ else
+ announce = TRUE;
+
+ silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid), &id_len);
+ name_len = strlen(channel->channel_name);
+
+ if (announce) {
+ len = 4 + name_len + id_len + 4;
+ *channels =
+ silc_buffer_realloc(*channels,
+ (*channels ?
+ silc_buffer_truelen((*channels)) +
+ len : len));
+ silc_buffer_pull_tail(*channels,
+ ((*channels)->end - (*channels)->data));
+ silc_buffer_format(*channels,
+ SILC_STR_UI_SHORT(name_len),
+ SILC_STR_UI_XNSTRING(channel->channel_name,
+ name_len),
+ SILC_STR_UI_SHORT(id_len),
SILC_STR_UI_XNSTRING(cid, id_len),
- SILC_STR_UI_INT(channel->mode),
- SILC_STR_END);
- silc_buffer_pull(*channels, len);
- }
+ SILC_STR_UI_INT(channel->mode),
+ SILC_STR_END);
+ silc_buffer_pull(*channels, len);
+ }
- if (creation_time && channel->updated < creation_time)
- announce = FALSE;
- else
- announce = TRUE;
-
- if (announce) {
- /* Channel user modes */
- *channel_users_modes = silc_realloc(*channel_users_modes,
- sizeof(**channel_users_modes) *
- (i + 1));
- (*channel_users_modes)[i] = NULL;
- *channel_modes = silc_realloc(*channel_modes,
- sizeof(**channel_modes) * (i + 1));
- (*channel_modes)[i] = NULL;
- *channel_ids = silc_realloc(*channel_ids,
+ if (creation_time && channel->updated < creation_time)
+ announce = FALSE;
+ else
+ announce = TRUE;
+
+ if (announce) {
+ /* Channel user modes */
+ *channel_users_modes = silc_realloc(*channel_users_modes,
+ sizeof(**channel_users_modes) *
+ (i + 1));
+ (*channel_users_modes)[i] = NULL;
+ *channel_modes = silc_realloc(*channel_modes,
+ sizeof(**channel_modes) * (i + 1));
+ (*channel_modes)[i] = NULL;
+ *channel_ids = silc_realloc(*channel_ids,
sizeof(**channel_ids) * (i + 1));
- (*channel_ids)[i] = NULL;
- silc_server_announce_get_channel_users(server, channel,
- &(*channel_modes)[i],
- channel_users,
- &(*channel_users_modes)[i]);
- (*channel_ids)[i] = channel->id;
-
- /* Channel's topic */
- *channel_topics = silc_realloc(*channel_topics,
- sizeof(**channel_topics) * (i + 1));
- (*channel_topics)[i] = NULL;
- silc_server_announce_get_channel_topic(server, channel,
- &(*channel_topics)[i]);
-
- /* Channel's invite and ban list */
- *channel_invites = silc_realloc(*channel_invites,
- sizeof(**channel_invites) * (i + 1));
- (*channel_invites)[i] = NULL;
- *channel_bans = silc_realloc(*channel_bans,
- sizeof(**channel_bans) * (i + 1));
- (*channel_bans)[i] = NULL;
- silc_server_announce_get_inviteban(server, channel,
- &(*channel_invites)[i],
- &(*channel_bans)[i]);
-
- (*channel_users_modes_c)++;
- silc_free(cid);
-
- i++;
- }
-
- if (!silc_idcache_list_next(list, &id_cache))
- break;
+ (*channel_ids)[i] = NULL;
+ silc_server_announce_get_channel_users(server, channel,
+ &(*channel_modes)[i],
+ channel_users,
+ &(*channel_users_modes)[i]);
+ (*channel_ids)[i] = channel->id;
+
+ /* Channel's topic */
+ *channel_topics = silc_realloc(*channel_topics,
+ sizeof(**channel_topics) * (i + 1));
+ (*channel_topics)[i] = NULL;
+ silc_server_announce_get_channel_topic(server, channel,
+ &(*channel_topics)[i]);
+
+ /* Channel's invite and ban list */
+ *channel_invites = silc_realloc(*channel_invites,
+ sizeof(**channel_invites) * (i + 1));
+ (*channel_invites)[i] = NULL;
+ *channel_bans = silc_realloc(*channel_bans,
+ sizeof(**channel_bans) * (i + 1));
+ (*channel_bans)[i] = NULL;
+ silc_server_announce_get_inviteban(server, channel,
+ &(*channel_invites)[i],
+ &(*channel_bans)[i]);
+
+ (*channel_users_modes_c)++;
+
+ i++;
}
}
-
- silc_idcache_list_free(list);
}
}
void silc_server_announce_channels(SilcServer server,
unsigned long creation_time,
- SilcSocketConnection remote)
+ SilcPacketStream remote)
{
SilcBuffer channels = NULL, *channel_modes = NULL, channel_users = NULL;
SilcBuffer *channel_users_modes = NULL;
if (channels) {
silc_buffer_push(channels, channels->data - channels->head);
- SILC_LOG_HEXDUMP(("channels"), channels->data, channels->len);
+ SILC_LOG_HEXDUMP(("channels"), channels->data, silc_buffer_len(channels));
/* Send the packet */
silc_server_packet_send(server, remote,
SILC_PACKET_NEW_CHANNEL, SILC_PACKET_FLAG_LIST,
- channels->data, channels->len,
- FALSE);
+ channels->data, silc_buffer_len(channels));
silc_buffer_free(channels);
}
if (channel_users) {
silc_buffer_push(channel_users, channel_users->data - channel_users->head);
SILC_LOG_HEXDUMP(("channel users"), channel_users->data,
- channel_users->len);
+ silc_buffer_len(channel_users));
/* Send the packet */
silc_server_packet_send(server, remote,
SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
- channel_users->data, channel_users->len,
- FALSE);
+ channel_users->data, silc_buffer_len(channel_users));
silc_buffer_free(channel_users);
}
channel_modes[i]->data -
channel_modes[i]->head);
SILC_LOG_HEXDUMP(("channel modes"), channel_modes[i]->data,
- channel_modes[i]->len);
+ silc_buffer_len(channel_modes[i]));
silc_server_packet_send_dest(server, remote,
SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
channel_ids[i], SILC_ID_CHANNEL,
channel_modes[i]->data,
- channel_modes[i]->len,
- FALSE);
+ silc_buffer_len(channel_modes[i]));
silc_buffer_free(channel_modes[i]);
}
silc_free(channel_modes);
channel_users_modes[i]->data -
channel_users_modes[i]->head);
SILC_LOG_HEXDUMP(("channel users modes"), channel_users_modes[i]->data,
- channel_users_modes[i]->len);
+ silc_buffer_len(channel_users_modes[i]));
silc_server_packet_send_dest(server, remote,
SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
channel_ids[i], SILC_ID_CHANNEL,
channel_users_modes[i]->data,
- channel_users_modes[i]->len,
- FALSE);
+ silc_buffer_len(channel_users_modes[i]));
silc_buffer_free(channel_users_modes[i]);
}
silc_free(channel_users_modes);
channel_topics[i]->data -
channel_topics[i]->head);
SILC_LOG_HEXDUMP(("channel topic"), channel_topics[i]->data,
- channel_topics[i]->len);
+ silc_buffer_len(channel_topics[i]));
silc_server_packet_send_dest(server, remote,
SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
channel_ids[i], SILC_ID_CHANNEL,
channel_topics[i]->data,
- channel_topics[i]->len,
- FALSE);
+ silc_buffer_len(channel_topics[i]));
silc_buffer_free(channel_topics[i]);
}
silc_free(channel_topics);
channel_invites[i]->data -
channel_invites[i]->head);
SILC_LOG_HEXDUMP(("channel invite list"), channel_invites[i]->data,
- channel_invites[i]->len);
+ silc_buffer_len(channel_invites[i]));
silc_server_packet_send_dest(server, remote,
SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
channel_ids[i], SILC_ID_CHANNEL,
channel_invites[i]->data,
- channel_invites[i]->len,
- FALSE);
+ silc_buffer_len(channel_invites[i]));
silc_buffer_free(channel_invites[i]);
}
silc_free(channel_invites);
channel_bans[i]->data -
channel_bans[i]->head);
SILC_LOG_HEXDUMP(("channel ban list"), channel_bans[i]->data,
- channel_bans[i]->len);
+ silc_buffer_len(channel_bans[i]));
silc_server_packet_send_dest(server, remote,
SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
channel_ids[i], SILC_ID_CHANNEL,
channel_bans[i]->data,
- channel_bans[i]->len,
- FALSE);
+ silc_buffer_len(channel_bans[i]));
silc_buffer_free(channel_bans[i]);
}
silc_free(channel_bans);
/* Announces WATCH list. */
void silc_server_announce_watches(SilcServer server,
- SilcSocketConnection remote)
+ SilcPacketStream remote)
{
SilcHashTableList htl;
SilcBuffer buffer, idp, args, pkp;
silc_buffer_format(args,
SILC_STR_UI_SHORT(1),
SILC_STR_END);
- pkp = silc_pkcs_public_key_payload_encode(key);
- args = silc_argument_payload_encode_one(args, pkp->data, pkp->len, 0x00);
+ pkp = silc_public_key_payload_encode(key);
+ args = silc_argument_payload_encode_one(args, pkp->data,
+ silc_buffer_len(pkp), 0x00);
buffer = silc_command_payload_encode_va(SILC_COMMAND_WATCH,
++server->cmd_ident, 2,
- 1, idp->data, idp->len,
- 4, args->data, args->len);
+ 1, idp->data, silc_buffer_len(idp),
+ 4, args->data,
+ silc_buffer_len(args));
/* Send command */
silc_server_packet_send(server, remote, SILC_PACKET_COMMAND, 0,
- buffer->data, buffer->len, TRUE);
+ buffer->data, silc_buffer_len(buffer));
silc_buffer_free(pkp);
silc_buffer_free(args);
/* Assembles user list and users mode list from the `channel'. */
-bool silc_server_get_users_on_channel(SilcServer server,
+SilcBool silc_server_get_users_on_channel(SilcServer server,
SilcChannelEntry channel,
SilcBuffer *user_list,
SilcBuffer *mode_list,
client_id_list = silc_buffer_alloc(len);
client_mode_list =
silc_buffer_alloc(4 * silc_hash_table_count(channel->user_list));
- silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
- silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
+ silc_buffer_pull_tail(client_id_list, silc_buffer_truelen(client_id_list));
+ silc_buffer_pull_tail(client_mode_list,
+ silc_buffer_truelen(client_mode_list));
silc_hash_table_list(channel->user_list, &htl);
while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
/* Client ID */
idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
- silc_buffer_put(client_id_list, idp->data, idp->len);
- silc_buffer_pull(client_id_list, idp->len);
+ silc_buffer_put(client_id_list, idp->data, silc_buffer_len(idp));
+ silc_buffer_pull(client_id_list, silc_buffer_len(idp));
silc_buffer_free(idp);
/* Client's mode on channel */
/* Saves users and their modes to the `channel'. */
void silc_server_save_users_on_channel(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcChannelEntry channel,
SilcClientID *noadd,
SilcBuffer user_list,
int i;
SilcUInt16 idp_len;
SilcUInt32 mode;
- SilcClientID *client_id;
+ SilcID id;
SilcClientEntry client;
SilcIDCacheEntry cache;
SilcChannelClientEntry chl;
/* Client ID */
SILC_GET16_MSB(idp_len, user_list->data + 2);
idp_len += 4;
- client_id = silc_id_payload_parse_id(user_list->data, idp_len, NULL);
- silc_buffer_pull(user_list, idp_len);
- if (!client_id)
+ if (!silc_id_payload_parse_id(user_list->data, idp_len, &id))
continue;
+ silc_buffer_pull(user_list, idp_len);
/* Mode */
SILC_GET32_MSB(mode, mode_list->data);
silc_buffer_pull(mode_list, 4);
- if (noadd && SILC_ID_CLIENT_COMPARE(client_id, noadd)) {
- silc_free(client_id);
+ if (noadd && SILC_ID_CLIENT_COMPARE(&id.u.client_id, noadd))
continue;
- }
cache = NULL;
/* Check if we have this client cached already. */
- client = silc_idlist_find_client_by_id(server->local_list, client_id,
+ client = silc_idlist_find_client_by_id(server->local_list,
+ &id.u.client_id,
server->server_type, &cache);
if (!client)
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, server->server_type,
- &cache);
+ &id.u.client_id,
+ server->server_type, &cache);
if (!client) {
/* If router did not find such Client ID in its lists then this must
be bogus client or some router in the net is buggy. */
- if (server->server_type != SILC_SERVER) {
- silc_free(client_id);
+ if (server->server_type != SILC_SERVER)
continue;
- }
/* We don't have that client anywhere, add it. The client is added
to global list since server didn't have it in the lists so it must be
global. */
client = silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
- silc_id_dup(client_id, SILC_ID_CLIENT),
- sock->user_data, NULL, 0);
+ silc_id_dup(&id.u.client_id,
+ SILC_ID_CLIENT),
+ silc_packet_get_context(sock),
+ NULL);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
- silc_free(client_id);
continue;
}
client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
}
- if (cache)
- cache->expire = 0;
- silc_free(client_id);
-
if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
SILC_LOG_ERROR(("Attempting to add unregistered client to channel ",
"%s", channel->channel_name));
it has joined. */
void silc_server_save_user_channels(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcClientEntry client,
SilcBuffer channels,
SilcBuffer channels_user_modes)
SilcUInt32 *chumodes;
SilcChannelPayload entry;
SilcChannelEntry channel;
- SilcChannelID *channel_id;
+ SilcChannelID channel_id;
SilcChannelClientEntry chl;
SilcHashTable ht = NULL;
SilcHashTableList htl;
!(client->data.status & SILC_IDLIST_STATUS_REGISTERED))
goto out;
- ch = silc_channel_payload_parse_list(channels->data, channels->len);
+ ch = silc_channel_payload_parse_list(channels->data,
+ silc_buffer_len(channels));
if (ch && silc_get_mode_list(channels_user_modes, silc_dlist_count(ch),
&chumodes)) {
ht = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL,
while ((entry = silc_dlist_get(ch)) != SILC_LIST_END) {
/* Check if we have this channel, and add it if we don't have it.
Also add the client on the channel unless it is there already. */
- channel_id = silc_channel_get_id_parse(entry);
+ if (!silc_channel_get_id_parse(entry, &channel_id))
+ continue;
channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
+ &channel_id, NULL);
if (!channel)
channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
+ &channel_id, NULL);
if (!channel) {
if (server->server_type != SILC_SERVER) {
- silc_free(channel_id);
i++;
continue;
}
/* We don't have that channel anywhere, add it. */
name = silc_channel_get_name(entry, NULL);
channel = silc_idlist_add_channel(server->global_list, strdup(name), 0,
- channel_id, server->router,
- NULL, NULL, 0);
+ silc_id_dup(&channel_id,
+ SILC_ID_CHANNEL),
+ server->router, NULL, NULL, 0);
if (!channel) {
- silc_free(channel_id);
i++;
continue;
}
- channel_id = NULL;
}
channel->mode = silc_channel_get_mode(entry);
}
silc_hash_table_add(ht, channel, channel);
- silc_free(channel_id);
}
silc_channel_payload_list_free(ch);
silc_free(chumodes);
could not be found to the client. If the `client_id' is specified then
it is used and the `id_data' is ignored. */
-SilcSocketConnection
+SilcPacketStream
silc_server_get_client_route(SilcServer server,
unsigned char *id_data,
SilcUInt32 id_len,
SilcIDListData *idata,
SilcClientEntry *client_entry)
{
- SilcClientID *id;
+ SilcClientID *id, clid;
SilcClientEntry client;
SILC_LOG_DEBUG(("Start"));
/* Decode destination Client ID */
if (!client_id) {
- id = silc_id_str2id(id_data, id_len, SILC_ID_CLIENT);
- if (!id) {
- SILC_LOG_ERROR(("Could not decode destination Client ID, dropped"));
+ if (!silc_id_str2id(id_data, id_len, SILC_ID_CHANNEL, &clid, sizeof(clid)))
return NULL;
- }
+ id = silc_id_dup(&clid, SILC_ID_CLIENT);
} else {
id = silc_id_dup(client_id, SILC_ID_CLIENT);
}
client = silc_idlist_find_client_by_id(server->global_list, id,
TRUE, NULL);
if (client) {
- SilcSocketConnection dst_sock;
+ SilcPacketStream dst_sock;
dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT);
silc_free(id);
if (idata && dst_sock)
- *idata = (SilcIDListData)dst_sock->user_data;
+ *idata = silc_packet_get_context(dst_sock);
return dst_sock;
}
}
SilcBuffer silc_server_get_client_channel_list(SilcServer server,
SilcClientEntry client,
- bool get_private,
- bool get_secret,
+ SilcBool get_private,
+ SilcBool get_secret,
SilcBuffer *user_mode_list)
{
SilcBuffer buffer = NULL;
SilcChannelEntry channel;
SilcChannelClientEntry chl;
SilcHashTableList htl;
- unsigned char *cid;
+ unsigned char cid[32];
SilcUInt32 id_len;
SilcUInt16 name_len;
int len;
if (channel->mode & SILC_CHANNEL_MODE_PRIVATE && !get_private)
continue;
- cid = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+ silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid), &id_len);
name_len = strlen(channel->channel_name);
len = 4 + name_len + id_len + 4;
buffer = silc_buffer_realloc(buffer,
- (buffer ? buffer->truelen + len : len));
+ (buffer ?
+ silc_buffer_truelen(buffer) + len : len));
silc_buffer_pull_tail(buffer, (buffer->end - buffer->data));
silc_buffer_format(buffer,
SILC_STR_UI_SHORT(name_len),
- SILC_STR_UI_XNSTRING(channel->channel_name,
- name_len),
+ SILC_STR_DATA(channel->channel_name, name_len),
SILC_STR_UI_SHORT(id_len),
- SILC_STR_UI_XNSTRING(cid, id_len),
+ SILC_STR_DATA(cid, id_len),
SILC_STR_UI_INT(chl->channel->mode),
SILC_STR_END);
silc_buffer_pull(buffer, len);
- silc_free(cid);
if (user_mode_list) {
- *user_mode_list = silc_buffer_realloc(*user_mode_list,
- (*user_mode_list ?
- (*user_mode_list)->truelen + 4 :
- 4));
+ *user_mode_list =
+ silc_buffer_realloc(*user_mode_list,
+ (*user_mode_list ?
+ silc_buffer_truelen((*user_mode_list)) + 4 : 4));
silc_buffer_pull_tail(*user_mode_list, ((*user_mode_list)->end -
(*user_mode_list)->data));
SILC_PUT32_MSB(chl->mode, (*user_mode_list)->data);
return buffer;
}
-/* Timeout callback for unsuccessful rekey. The rekey did not go through
- for some reason. */
-
-SILC_TASK_CALLBACK(silc_server_rekey_timeout)
-{
- SilcServerRekeyInternalContext *ctx = context;
- SilcServer server = app_context;
- SilcSocketConnection sock = ctx->sock;
-
- SILC_LOG_DEBUG(("Timeout occurred in rekey protocol with %s:%d [%s]",
- sock->hostname, sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
-
- SILC_LOG_WARNING(("Timeout occurred in rekey protocol with %s:%d [%s]",
- sock->hostname, sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
-
- if (sock->protocol) {
- silc_protocol_cancel(sock->protocol, server->schedule);
- silc_protocol_free(sock->protocol);
- sock->protocol = NULL;
- }
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- if (ctx->ske)
- silc_ske_free(ctx->ske);
- silc_socket_free(sock);
- silc_free(ctx);
-
- /* Disconnect since we failed to rekey, the keys are probably wrong. */
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
-
- /* Reconnect */
- if (sock->type != SILC_SOCKET_TYPE_CLIENT)
- silc_server_create_connections(server);
-}
-
-/* A timeout callback for the re-key. We will be the initiator of the
- re-key protocol. */
-
-SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_callback)
-{
- SilcServer server = app_context;
- SilcSocketConnection sock = (SilcSocketConnection)context;
- SilcIDListData idata = (SilcIDListData)sock->user_data;
- SilcProtocol protocol;
- SilcServerRekeyInternalContext *proto_ctx;
-
- if (!idata)
- return;
-
- /* Do not execute rekey with disabled connections, as it would not
- go through anyway. */
- if (idata->status & SILC_IDLIST_STATUS_DISABLED)
- return;
-
- /* If rekey protocol is active already wait for it to finish */
- if (sock->protocol && sock->protocol->protocol &&
- sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)
- return;
-
- /* If any other protocol is active do not start this protocol yet. */
- if (sock->protocol) {
- SILC_LOG_DEBUG(("Waiting for other protocol to finish before rekeying"));
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rekey_callback,
- sock, 60, 0, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- return;
- }
-
- SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s]",
- sock->hostname, sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
-
- /* Allocate internal protocol context. This is sent as context
- to the protocol. */
- proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
- proto_ctx->server = (void *)server;
- proto_ctx->sock = silc_socket_dup(sock);
- proto_ctx->responder = FALSE;
- proto_ctx->pfs = idata->rekey->pfs;
-
- /* Perform rekey protocol. Will call the final callback after the
- protocol is over. */
- silc_protocol_alloc(SILC_PROTOCOL_SERVER_REKEY,
- &protocol, proto_ctx, silc_server_rekey_final);
- sock->protocol = protocol;
-
- /* Register timeout callback in case the rekey does not go through. */
- proto_ctx->timeout_task =
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rekey_timeout,
- proto_ctx,
- (idata->rekey->timeout >
- server->config->key_exchange_timeout ?
- idata->rekey->timeout :
- server->config->key_exchange_timeout * 4), 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_LOW);
-
- /* Run the protocol */
- silc_protocol_execute(protocol, server->schedule, 0, 0);
-}
-
-/* The final callback for the REKEY protocol. This will actually take the
- new key material into use. */
-
-SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_final)
-{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerRekeyInternalContext *ctx =
- (SilcServerRekeyInternalContext *)protocol->context;
- SilcServer server = (SilcServer)ctx->server;
- SilcSocketConnection sock = ctx->sock;
- SilcIDListData idata = (SilcIDListData)sock->user_data;
-
- if (ctx->timeout_task)
- silc_schedule_task_del(server->schedule, ctx->timeout_task);
-
- if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
- protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
- /* Error occured during protocol */
- SILC_LOG_ERROR(("Error occurred during rekey protocol with "
- "%s (%s)", sock->hostname, sock->ip));
- silc_protocol_cancel(protocol, server->schedule);
- silc_protocol_free(protocol);
- sock->protocol = NULL;
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- if (ctx->ske)
- silc_ske_free(ctx->ske);
- silc_socket_free(sock);
- silc_free(ctx);
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
-
- /* Reconnect */
- if (sock->type != SILC_SOCKET_TYPE_CLIENT)
- silc_server_create_connections(server);
- return;
- }
-
- SILC_LOG_DEBUG(("Rekey protocol completed with %s:%d [%s]",
- sock->hostname, sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
-
- /* Purge the outgoing data queue to assure that all rekey packets really
- go to the network before we quit the protocol. */
- silc_server_packet_queue_purge(server, sock);
-
- /* Re-register re-key timeout */
- if (ctx->responder == FALSE)
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rekey_callback,
- sock, idata->rekey->timeout, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-
- /* Cleanup */
- silc_protocol_free(protocol);
- sock->protocol = NULL;
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- if (ctx->ske)
- silc_ske_free(ctx->ske);
- silc_socket_free(sock);
- silc_free(ctx);
-}
-
/* Task callback used to retrieve network statistical information from
router server once in a while. */
idp = silc_id_payload_encode(server->router->id, SILC_ID_SERVER);
packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
++server->cmd_ident, 1,
- 1, idp->data, idp->len);
+ 1, idp->data,
+ silc_buffer_len(idp));
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
SILC_PACKET_COMMAND, 0, packet->data,
- packet->len, FALSE);
+ silc_buffer_len(packet));
silc_buffer_free(packet);
silc_buffer_free(idp);
}
- silc_schedule_task_add(server->schedule, 0, silc_server_get_stats,
- server, 120, 0, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_LOW);
+ silc_schedule_task_add_timeout(server->schedule, silc_server_get_stats,
+ server, 120, 0);
}
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2005, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#ifndef SERVER_H
#define SERVER_H
-/* Forward declaration of backup server context */
+/* Forward declarations */
+typedef struct SilcServerEntryStruct *SilcServerEntry;
+typedef struct SilcClientEntryStruct *SilcClientEntry;
+typedef struct SilcChannelEntryStruct *SilcChannelEntry;
typedef struct SilcServerBackupStruct *SilcServerBackup;
+typedef struct SilcIDListDataObject *SilcIDListData, SilcIDListDataStruct;
+typedef struct SilcIDListStruct *SilcIDList;
/* Callback function that is called after the key exchange and connection
authentication protocols has been completed with a remote router. The
`server_entry' is the remote router entry or NULL on error. */
-typedef void (*SilcServerConnectRouterCallback)(SilcServer server,
- SilcServerEntry server_entry,
- void *context);
+typedef void (*SilcServerConnectCallback)(SilcServer server,
+ SilcServerEntry server_entry,
+ void *context);
/* Connection structure used when connection to remote */
-typedef struct {
- SilcSocketConnection sock;
+typedef struct SilcServerConnectionStruct {
+ SilcServer server;
+ SilcStream stream;
+ SilcPacketStream sock;
+ SilcAsyncOperation op;
+ SilcServerConfigRef conn;
- /* Remote host name and port */
char *remote_host;
int remote_port;
- bool backup;
+
char *backup_replace_ip;
int backup_replace_port;
- bool no_reconnect;
-
- /* Connection configuration (maybe NULL) */
- SilcServerConfigRef conn;
/* Current connection retry info */
SilcUInt32 retry_count;
SilcUInt32 retry_timeout;
-
- SilcServerConnectRouterCallback callback;
+ SilcServerConnectCallback callback;
void *callback_context;
+ int rekey_timeout;
+
+ unsigned int backup : 1; /* Set when backup router connection */
+ unsigned int backup_resuming : 1; /* Set when running resuming protocol */
+ unsigned int no_reconnect : 1; /* Set when to not reconnect */
+ unsigned int no_conf : 1; /* Set when connecting without pre-
+ configuration. */
} *SilcServerConnection;
/* General definitions */
(sock->protocol && sock->protocol->protocol && \
sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)
-/* Check whether backup resuming protocol is active */
-#define SILC_SERVER_IS_BACKUP(sock) \
- (sock->protocol && sock->protocol->protocol && \
- sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP)
-
/* Output a message to stderr or to the appropriate log facility wether
we are in the background or not. */
#define SILC_SERVER_LOG_INFO(fmt) \
silc_server_stderr(SILC_LOG_WARNING, silc_format fmt)
/* Prototypes */
-int silc_server_alloc(SilcServer *new_server);
+SilcBool silc_server_alloc(SilcServer *new_server);
void silc_server_free(SilcServer server);
-bool silc_server_init(SilcServer server);
-bool silc_server_rehash(SilcServer server);
+SilcBool silc_server_init(SilcServer server);
+SilcBool silc_server_rehash(SilcServer server);
void silc_server_run(SilcServer server);
void silc_server_stop(SilcServer server);
-void silc_server_start_key_exchange(SilcServer server,
- SilcServerConnection sconn,
- int sock);
-bool silc_server_packet_parse(SilcPacketParserContext *parser_context,
- void *context);
-void silc_server_packet_parse_type(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
+void silc_server_start_key_exchange(SilcServerConnection sconn);
void silc_server_create_connection(SilcServer server,
- const char *remote_host, SilcUInt32 port);
+ SilcBool reconnect,
+ const char *remote_host, SilcUInt32 port,
+ SilcServerConnectCallback callback,
+ void *context);
void silc_server_close_connection(SilcServer server,
- SilcSocketConnection sock);
+ SilcPacketStream sock);
void silc_server_free_client_data(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcClientEntry client,
int notify,
const char *signoff);
void silc_server_free_sock_user_data(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
const char *signoff_message);
void silc_server_remove_from_channels(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcClientEntry client,
- bool notify,
+ SilcBool notify,
const char *signoff_message,
- bool keygen, bool killed);
-bool silc_server_remove_from_one_channel(SilcServer server,
- SilcSocketConnection sock,
+ SilcBool keygen, bool killed);
+SilcBool silc_server_remove_from_one_channel(SilcServer server,
+ SilcPacketStream sock,
SilcChannelEntry channel,
SilcClientEntry client,
- bool notify);
+ SilcBool notify);
void silc_server_disconnect_remote(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcStatus status, ...);
SilcChannelEntry silc_server_create_new_channel(SilcServer server,
SilcServerID *router_id,
char *channel_name,
SilcChannelID *channel_id,
int broadcast);
-bool silc_server_create_channel_key(SilcServer server,
+SilcBool silc_server_create_channel_key(SilcServer server,
SilcChannelEntry channel,
SilcUInt32 key_len);
SilcChannelEntry silc_server_save_channel_key(SilcServer server,
SilcBuffer key_payload,
SilcChannelEntry channel);
-void silc_server_perform_heartbeat(SilcSocketConnection sock,
+void silc_server_perform_heartbeat(SilcPacketStream sock,
void *hb_context);
void silc_server_announce_get_channel_topic(SilcServer server,
SilcChannelEntry channel,
SilcBuffer **channel_bans,
SilcChannelID ***channel_ids,
unsigned long creation_time);
-void silc_server_announce_servers(SilcServer server, bool global,
+void silc_server_announce_servers(SilcServer server, SilcBool global,
unsigned long creation_time,
- SilcSocketConnection remote);
+ SilcPacketStream remote);
void silc_server_announce_clients(SilcServer server,
unsigned long creation_time,
- SilcSocketConnection remote);
+ SilcPacketStream remote);
void silc_server_announce_channels(SilcServer server,
unsigned long creation_time,
- SilcSocketConnection remote);
+ SilcPacketStream remote);
void silc_server_announce_watches(SilcServer server,
- SilcSocketConnection remote);
-bool silc_server_get_users_on_channel(SilcServer server,
+ SilcPacketStream remote);
+SilcBool silc_server_get_users_on_channel(SilcServer server,
SilcChannelEntry channel,
SilcBuffer *user_list,
SilcBuffer *mode_list,
SilcUInt32 *user_count);
void silc_server_save_users_on_channel(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcChannelEntry channel,
SilcClientID *noadd,
SilcBuffer user_list,
SilcBuffer mode_list,
SilcUInt32 user_count);
void silc_server_save_user_channels(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcClientEntry client,
SilcBuffer channels,
SilcBuffer channels_user_modes);
-SilcSocketConnection
+SilcPacketStream
silc_server_get_client_route(SilcServer server,
unsigned char *id_data,
SilcUInt32 id_len,
SilcClientEntry *client_entry);
SilcBuffer silc_server_get_client_channel_list(SilcServer server,
SilcClientEntry client,
- bool get_private,
- bool get_secret,
+ SilcBool get_private,
+ SilcBool get_secret,
SilcBuffer *user_mode_list);
void silc_server_stderr(SilcLogType type, char *message);
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2005 Pekka Riikonen
+ Copyright (C) 2001 - 2005, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
SilcServerEntry server;
SilcIDIP ip;
SilcUInt16 port;
- bool local;
+ SilcBool local;
} SilcServerBackupEntry;
/* Holds IP address and port of the primary router that was replaced
typedef struct {
SilcUInt8 session;
- bool connected;
+ SilcBool connected;
SilcServerEntry server_entry;
} SilcServerBackupProtocolSession;
/* Backup resuming protocol context */
typedef struct {
SilcServer server;
- SilcSocketConnection sock;
+ SilcPacketStream sock;
SilcUInt8 type;
SilcUInt8 session;
SilcServerBackupProtocolSession *sessions;
unsigned int responder : 1;
unsigned int received_failure : 1;
unsigned int timeout : 1;
+ unsigned int error : 1;
} *SilcServerBackupProtocolContext;
in the local cell, if FALSE it is in some other cell. */
void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
- const char *ip, int port, bool local)
+ const char *ip, int port, SilcBool local)
{
int i;
}
SILC_LOG_DEBUG(("Backup router %s will replace %s",
- ((SilcSocketConnection)backup_server->connection)->ip,
- ip, port));
+ backup_server->data.sconn->remote_host, ip, port));
for (i = 0; i < server->backup->servers_count; i++) {
if (!server->backup->servers[i].server) {
and the bacup router entry to the `server' pointer if non-NULL. Returns
FALSE if the router is not replaced by backup router. */
-bool silc_server_backup_replaced_get(SilcServer server,
- SilcServerID *server_id,
- SilcServerEntry *server_entry)
+SilcBool silc_server_backup_replaced_get(SilcServer server,
+ SilcServerID *server_id,
+ SilcServerEntry *server_entry)
{
int i;
that the caller already knows that the `packet' is broadcast packet. */
void silc_server_backup_broadcast(SilcServer server,
- SilcSocketConnection sender,
- SilcPacketContext *packet)
+ SilcPacketStream sender,
+ SilcPacket packet)
{
SilcServerEntry backup;
- SilcSocketConnection sock;
- SilcBuffer buffer;
- const SilcBufferStruct p;
- SilcIDListData idata;
+ SilcPacketStream sock;
int i;
if (!server->backup || server->server_type != SILC_ROUTER)
SILC_LOG_DEBUG(("Broadcasting received packet to backup routers"));
- buffer = packet->buffer;
- silc_buffer_push(buffer, buffer->data - buffer->head);
-
for (i = 0; i < server->backup->servers_count; i++) {
backup = server->backup->servers[i].server;
if (server->backup->servers[i].server == server->id_entry)
continue;
- idata = (SilcIDListData)backup;
sock = backup->connection;
-
- if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send,
- (const SilcBuffer)&p)) {
- SILC_LOG_ERROR(("Cannot send packet"));
- return;
- }
- silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
- silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++,
- (SilcBuffer)&p, p.len);
-
- SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", p.len), p.data, p.len);
-
- /* Now actually send the packet */
- silc_server_packet_send_real(server, sock, FALSE);
-
- /* Check for mandatory rekey */
- if (idata->psn_send == SILC_SERVER_REKEY_THRESHOLD)
- silc_schedule_task_add(server->schedule, sender->sock,
- silc_server_rekey_callback, sender, 0, 1,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ silc_server_packet_route(server, sock, packet);
}
}
SilcPacketFlags flags,
unsigned char *data,
SilcUInt32 data_len,
- bool force_send,
- bool local)
+ SilcBool force_send,
+ SilcBool local)
{
SilcServerEntry backup;
- SilcSocketConnection sock;
+ SilcPacketStream sock;
int i;
if (!server->backup || server->server_type != SILC_ROUTER)
sock = backup->connection;
- SILC_LOG_DEBUG(("Sending %s packet to backup router %s (%s)",
- silc_get_packet_name(type), sock->hostname, sock->ip));
-
silc_server_packet_send(server, backup->connection, type, flags,
- data, data_len, force_send);
+ data, data_len);
}
}
SilcIdType dst_id_type,
unsigned char *data,
SilcUInt32 data_len,
- bool force_send,
- bool local)
+ SilcBool force_send,
+ SilcBool local)
{
SilcServerEntry backup;
- SilcSocketConnection sock;
+ SilcPacketStream sock;
int i;
if (!server->backup || server->server_type != SILC_ROUTER)
sock = backup->connection;
- SILC_LOG_DEBUG(("Sending %s packet to backup router %s (%s)",
- silc_get_packet_name(type), sock->hostname, sock->ip));
-
silc_server_packet_send_dest(server, backup->connection, type, flags,
- dst_id, dst_id_type, data, data_len,
- force_send);
+ dst_id, dst_id_type, data, data_len);
}
}
SILC_PACKET_RESUME_ROUTER. */
void silc_server_backup_send_start_use(SilcServer server,
- SilcSocketConnection sock,
- bool failure)
+ SilcPacketStream sock,
+ SilcBool failure)
{
unsigned char data[4];
- SILC_LOG_DEBUG(("Sending START_USE (%s) to %s",
- failure ? "failure" : "success", sock->ip));
+ SILC_LOG_DEBUG(("Sending START_USE (%s)",
+ failure ? "failure" : "success"));
if (failure) {
SILC_PUT32_MSB(SILC_SERVER_BACKUP_START_USE, data);
silc_server_packet_send(server, sock, SILC_PACKET_FAILURE, 0,
- data, 4, FALSE);
+ data, 4);
} else {
data[0] = SILC_SERVER_BACKUP_START_USE;
data[1] = 0;
silc_server_packet_send(server, sock,
SILC_PACKET_RESUME_ROUTER, 0,
- data, 2, FALSE);
+ data, 2);
}
}
online. This is not sent by backup router or any other server. */
void silc_server_backup_send_replaced(SilcServer server,
- SilcSocketConnection sock)
+ SilcPacketStream sock)
{
unsigned char data[4];
- SILC_LOG_DEBUG(("Sending REPLACED (%s) to %s", sock->ip));
+ SILC_LOG_DEBUG(("Sending REPLACED"));
data[0] = SILC_SERVER_BACKUP_REPLACED;
data[1] = 0;
silc_server_packet_send(server, sock,
SILC_PACKET_RESUME_ROUTER, 0,
- data, 2, FALSE);
+ data, 2);
}
SILC_TASK_CALLBACK(silc_server_backup_timeout)
{
- SilcProtocol protocol = context;
- SilcServerBackupProtocolContext ctx = protocol->context;
+ SilcServerBackupProtocolContext ctx = context;
SilcServer server = app_context;
SILC_LOG_INFO(("Timeout occurred during backup resuming protocol"));
ctx->timeout = TRUE;
- silc_protocol_cancel(protocol, server->schedule);
- protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute_final(protocol, server->schedule);
+ ctx->error = TRUE;
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_protocol_backup_done, context,
+ 0, 0);
}
/* Callback to start the protocol as responder */
SILC_TASK_CALLBACK(silc_server_backup_responder_start)
{
SilcServerBackupProtocolContext proto_ctx = context;
- SilcSocketConnection sock = proto_ctx->sock;
+ SilcPacketStream sock = proto_ctx->sock;
+ SilcIDListData idata = silc_packet_get_context(sock);
SilcServer server = app_context;
/* If other protocol is executing at the same time, start with timeout. */
- if (sock->protocol) {
+ if (idata->sconn->op) {
SILC_LOG_DEBUG(("Other protocol is executing, wait for it to finish"));
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_backup_responder_start,
- proto_ctx, 2, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_responder_start,
+ proto_ctx, 2, 0);
return;
}
+ /* Register protocol timeout */
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_timeout,
+ proto_ctx, 30, 0);
+
/* Run the backup resuming protocol */
- silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
- &sock->protocol, proto_ctx,
- silc_server_protocol_backup_done);
- silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_backup_timeout,
- sock->protocol, 30, 0, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_protocol_backup,
+ proto_ctx, 0, 0);
}
/* Callback to send START_USE to backup to check whether using backup
SILC_TASK_CALLBACK(silc_server_backup_check_status)
{
- SilcSocketConnection sock = context;
+ SilcPacketStream sock = context;
SilcServer server = app_context;
/* Check whether we are still using backup */
return;
silc_server_backup_send_start_use(server, sock, FALSE);
- silc_socket_free(sock); /* unref */
+ silc_packet_stream_unref(sock);
}
typedef struct {
SilcServer server;
- SilcSocketConnection sock;
- SilcPacketContext *packet;
+ SilcPacketStream sock;
+ SilcPacket packet;
} *SilcServerBackupPing;
/* PING command reply callback */
if (cmdr && !silc_command_get_status(cmdr->payload, NULL, NULL)) {
/* Timeout error occurred, the primary is really down. */
- SilcSocketConnection primary = SILC_PRIMARY_ROUTE(pc->server);
+ SilcPacketStream primary = SILC_PRIMARY_ROUTE(pc->server);
SILC_LOG_DEBUG(("PING timeout, primary is down"));
if (primary) {
- if (primary->user_data)
- silc_server_free_sock_user_data(pc->server, primary, NULL);
- SILC_SET_DISCONNECTING(primary);
+ silc_server_free_sock_user_data(pc->server, primary, NULL);
silc_server_close_connection(pc->server, primary);
}
silc_server_backup_send_start_use(pc->server, pc->sock, TRUE);
}
- silc_socket_free(pc->sock);
- silc_packet_context_free(pc->packet);
+ silc_packet_stream_unref(pc->sock);
+ silc_packet_free(pc->packet);
silc_free(pc);
}
start command is received. */
void silc_server_backup_resume_router(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+ SilcPacketStream sock,
+ SilcPacket packet)
{
+ SilcIDListData idata = silc_packet_get_context(sock);
SilcUInt8 type, session;
SilcServerBackupProtocolContext ctx;
- SilcIDListData idata;
int i, ret;
SILC_LOG_DEBUG(("Received RESUME_ROUTER packet"));
- if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
- sock->type == SILC_SOCKET_TYPE_UNKNOWN) {
+ if (idata->conn_type == SILC_CONN_CLIENT ||
+ idata->conn_type == SILC_CONN_UNKNOWN) {
SILC_LOG_DEBUG(("Bad packet received"));
+ silc_packet_free(packet);
return;
}
- idata = (SilcIDListData)sock->user_data;
-
- ret = silc_buffer_unformat(packet->buffer,
+ ret = silc_buffer_unformat(&packet->buffer,
SILC_STR_UI_CHAR(&type),
SILC_STR_UI_CHAR(&session),
SILC_STR_END);
if (ret < 0) {
SILC_LOG_ERROR(("Malformed resume router packet received"));
+ silc_packet_free(packet);
return;
}
if (server->server_type == SILC_SERVER) {
/* Nothing to do here actually, since we have switched already. */
SILC_LOG_DEBUG(("Received successful START_USE from backup router"));
+ silc_packet_free(packet);
return;
}
/* If we are marked as router then the primary is down and we send
success START_USE back to the server. */
if (server->server_type == SILC_ROUTER) {
- SILC_LOG_DEBUG(("Sending success START_USE back to %s", sock->ip));
+ SILC_LOG_DEBUG(("Sending success START_USE back"));
silc_server_backup_send_start_use(server, sock, FALSE);
+ silc_packet_free(packet);
return;
}
/* We have just lost primary, send success START_USE back */
if (server->standalone) {
- SILC_LOG_DEBUG(("We are stanalone, sending success START_USE back to %s",
- sock->ip));
+ SILC_LOG_DEBUG(("We are stanalone, sending success START_USE back"));
silc_server_backup_send_start_use(server, sock, FALSE);
+ silc_packet_free(packet);
return;
}
idp = silc_id_payload_encode(server->router->id, SILC_ID_SERVER);
silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
SILC_COMMAND_PING, ++server->cmd_ident, 1,
- 1, idp->data, idp->len);
+ 1, idp->data, silc_buffer_len(idp));
silc_buffer_free(idp);
/* Reprocess this packet after received reply from router */
pc = silc_calloc(1, sizeof(*pc));
pc->server = server;
- pc->sock = silc_socket_dup(sock);
- pc->packet = silc_packet_context_dup(packet);
+ pc->sock = sock;
+ pc->packet = packet;
+ silc_packet_stream_ref(sock);
silc_server_command_pending_timed(server, SILC_COMMAND_PING,
server->cmd_ident,
silc_server_backup_ping_reply, pc, 15);
"primary router"));
SILC_PUT32_MSB(SILC_SERVER_BACKUP_START, data);
silc_server_packet_send(server, sock, SILC_PACKET_FAILURE, 0,
- data, 4, FALSE);
+ data, 4);
server->backup_closed = FALSE;
+ silc_packet_free(packet);
return;
}
proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
proto_ctx->server = server;
- proto_ctx->sock = silc_socket_dup(sock);
+ proto_ctx->sock = sock;
proto_ctx->responder = TRUE;
proto_ctx->type = type;
proto_ctx->session = session;
proto_ctx->start = time(0);
+ silc_packet_stream_ref(sock);
SILC_LOG_DEBUG(("Starting backup resuming protocol as responder"));
SILC_LOG_INFO(("Starting backup resuming protocol"));
/* Start protocol immediately */
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_backup_responder_start,
- proto_ctx, 0, 1,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_responder_start,
+ proto_ctx, 0, 1);
return;
}
-
/* If we are router and the packet is coming from our primary router
then it means we have been replaced by an backup router in our cell. */
if (type == SILC_SERVER_BACKUP_REPLACED &&
server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_ROUTER &&
+ idata->conn_type == SILC_CONN_ROUTER &&
SILC_PRIMARY_ROUTE(server) == sock) {
/* We have been replaced by an backup router in our cell. We must
mark our primary router connection disabled since we are not allowed
SILC_LOG_INFO(("We are replaced by an backup router in this cell, will "
"wait until backup resuming protocol is executed"));
idata->status |= SILC_IDLIST_STATUS_DISABLED;
+ silc_packet_free(packet);
return;
}
-
+#if 0
/* Activate the shared protocol context for this socket connection
if necessary */
if (type == SILC_SERVER_BACKUP_RESUMED &&
- sock->type == SILC_SOCKET_TYPE_ROUTER && !sock->protocol &&
+ idata->conn_type == SILC_CONN_ROUTER && !sock->protocol &&
idata->status & SILC_IDLIST_STATUS_DISABLED) {
SilcServerEntry backup_router;
if (silc_server_backup_replaced_get(server, ((SilcServerEntry)idata)->id,
&backup_router)) {
- SilcSocketConnection bsock =
+ SilcPacketStream bsock =
(SilcSocketConnection)backup_router->connection;
if (bsock->protocol && bsock->protocol->protocol &&
bsock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
if (session == ctx->sessions[i].session) {
ctx->session = session;
silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
+ silc_packet_free(packet);
return;
}
}
/* If RESUMED received the session ID is zero, execute the protocol. */
if (type == SILC_SERVER_BACKUP_RESUMED) {
silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
+ silc_packet_free(packet);
return;
}
SILC_LOG_ERROR(("Unknown backup resuming session %d", session));
+ silc_packet_free(packet);
return;
}
-}
+#endif /* 0 */
-/* callback for async connection to remote router */
-
-SILC_TASK_CALLBACK(silc_server_backup_connection_established)
-{
- SilcServer server = app_context;
- SilcServerConnection sconn = (SilcServerConnection)context;
- int sock = fd;
- int opt = EINVAL, optlen = sizeof(opt);
-
- silc_schedule_task_del_by_fd(server->schedule, sock);
- silc_schedule_unset_listen_fd(server->schedule, sock);
-
- if (silc_net_get_socket_opt(sock, SOL_SOCKET, SO_ERROR, &opt, &optlen) ||
- (opt != 0)) {
- SILC_LOG_DEBUG(("Could not connect to router %s:%d: %s", sconn->remote_host,
- sconn->remote_port, strerror(opt)));
-
- if (server->server_type == SILC_SERVER) {
- sconn->retry_count++;
- if (sconn->retry_count > 3) {
- silc_free(sconn->remote_host);
- silc_free(sconn);
- return;
- }
- }
- silc_schedule_task_add(server->schedule, 0,
- silc_server_backup_connect_to_router,
- context, 10, 0, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- return;
- }
-
- SILC_LOG_DEBUG(("Connection to router %s:%d established", sconn->remote_host,
- sconn->remote_port));
-
- /* Continue with key exchange protocol */
- silc_server_start_key_exchange(server, sconn, sock);
-}
-
-
-/* Timeout task callback to connect to remote router */
-
-SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
-{
- SilcServer server = app_context;
- SilcServerConnection sconn = (SilcServerConnection)context;
- int sock;
- const char *server_ip;
-
- SILC_LOG_DEBUG(("Connecting to router %s:%d", sconn->remote_host,
- sconn->remote_port));
-
- /* Connect to remote host */
- server_ip = server->config->server_info->primary == NULL ? NULL :
- server->config->server_info->primary->server_ip;
- sock = silc_net_create_connection_async(server_ip, sconn->remote_port,
- sconn->remote_host);
- if (sock < 0) {
- if (server->server_type == SILC_SERVER) {
- sconn->retry_count++;
- if (sconn->retry_count > 3) {
- silc_free(sconn->remote_host);
- silc_free(sconn);
- return;
- }
- }
- silc_schedule_task_add(server->schedule, 0,
- silc_server_backup_connect_to_router,
- context, 10, 0, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- return;
- }
-
- /* wait for the connection to be established */
- silc_schedule_task_add(server->schedule, sock,
- silc_server_backup_connection_established,
- context, 0, 0, SILC_TASK_FD,
- SILC_TASK_PRI_NORMAL);
- silc_schedule_set_listen_fd(server->schedule, sock,
- SILC_TASK_WRITE, FALSE);
-}
-
-/* Constantly tries to reconnect to a primary router indicated by the
- `ip' and `port'. The `connected' callback will be called when the
- connection is created. */
-
-void silc_server_backup_reconnect(SilcServer server,
- const char *ip, SilcUInt16 port,
- SilcServerConnectRouterCallback callback,
- void *context)
-{
- SilcServerConnection sconn;
-
- SILC_LOG_INFO(("Attempting to reconnect to primary router"));
-
- sconn = silc_calloc(1, sizeof(*sconn));
- sconn->remote_host = strdup(ip);
- sconn->remote_port = port;
- sconn->callback = callback;
- sconn->callback_context = context;
- sconn->no_reconnect = TRUE;
- sconn->retry_count = 0;
- silc_schedule_task_add(server->schedule, 0,
- silc_server_backup_connect_to_router,
- sconn, 1, 0, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ silc_packet_free(packet);
}
/* Task that is called after backup router has connected back to
SilcServerBackupProtocolContext proto_ctx =
(SilcServerBackupProtocolContext)context;
SilcServer server = proto_ctx->server;
- SilcSocketConnection sock = proto_ctx->sock;
-
- /* If running other protocol already run this one a bit later. */
- if (sock->protocol) {
- SILC_LOG_DEBUG(("Other protocol is running, wait for it to finish"));
- silc_schedule_task_add(server->schedule, 0,
- silc_server_backup_connected_later,
- proto_ctx, 15, 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- return;
- }
+ SilcPacketStream sock = proto_ctx->sock;
SILC_LOG_DEBUG(("Starting backup resuming protocol as initiator"));
SILC_LOG_INFO(("Starting backup resuming protocol"));
+ /* Register protocol timeout */
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_timeout,
+ proto_ctx, 30, 0);
+
/* Run the backup resuming protocol */
- silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
- &sock->protocol, proto_ctx,
- silc_server_protocol_backup_done);
- silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
-
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_backup_timeout,
- sock->protocol, 30, 0, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_protocol_backup,
+ proto_ctx, 0, 0);
+}
+
+SILC_TASK_CALLBACK(silc_server_backup_connected_again)
+{
+ SilcServer server = app_context;
+ SilcServerConfigRouter *primary;
+
+ primary = silc_server_config_get_primary_router(server);
+ if (primary) {
+ if (!silc_server_find_socket_by_host(server, SILC_CONN_ROUTER,
+ primary->host, primary->port))
+ silc_server_create_connection(server, FALSE,
+ primary->host, primary->port,
+ silc_server_backup_connected,
+ context);
+ }
}
/* Called when we've established connection back to our primary router
void *context)
{
SilcServerBackupProtocolContext proto_ctx;
- SilcSocketConnection sock;
+ SilcPacketStream sock;
if (!server_entry) {
/* Try again */
- SilcServerConfigRouter *primary;
- primary = silc_server_config_get_primary_router(server);
- if (primary) {
- if (!silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_ROUTER,
- primary->host, primary->port))
- silc_server_backup_reconnect(server,
- primary->host, primary->port,
- silc_server_backup_connected,
- context);
- }
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_connected_again,
+ context, 0, 0);
return;
}
- sock = (SilcSocketConnection)server_entry->connection;
+ sock = server_entry->connection;
proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
proto_ctx->server = server;
- proto_ctx->sock = silc_socket_dup(sock);
+ proto_ctx->sock = sock;
proto_ctx->responder = FALSE;
proto_ctx->type = SILC_SERVER_BACKUP_START;
proto_ctx->start = time(0);
+ silc_packet_stream_ref(sock);
/* Start through scheduler */
- silc_schedule_task_add(server->schedule, 0,
- silc_server_backup_connected_later,
- proto_ctx, 0, 1,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_connected_later,
+ proto_ctx, 0, 1);
+}
+
+SILC_TASK_CALLBACK(silc_server_backup_connect_primary_again)
+{
+ SilcServer server = app_context;
+ SilcServerConfigRouter *primary;
+
+ primary = silc_server_config_get_primary_router(server);
+ if (primary) {
+ if (!silc_server_find_socket_by_host(server, SILC_CONN_ROUTER,
+ primary->host, primary->port))
+ silc_server_create_connection(server, FALSE,
+ primary->host, primary->port,
+ silc_server_backup_connect_primary,
+ context);
+ }
}
/* Called when normal server has connected to its primary router after
SilcServerEntry server_entry,
void *context)
{
- SilcSocketConnection backup_router = (SilcSocketConnection)context;
+#if 0
+ SilcPacketStream backup_router = context;
SilcServerBackupProtocolContext ctx;
- SilcSocketConnection sock;
+ SilcPacketStream sock;
SilcIDListData idata;
unsigned char data[2];
- if (SILC_IS_DISCONNECTING(backup_router) ||
- SILC_IS_DISCONNECTED(backup_router)) {
- silc_socket_free(backup_router);
- return;
- }
-
if (!server_entry) {
/* Try again */
- SilcServerConfigRouter *primary;
- primary = silc_server_config_get_primary_router(server);
- if (primary)
- if (!silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_ROUTER,
- primary->host, primary->port))
- silc_server_backup_reconnect(server,
- primary->host, primary->port,
- silc_server_backup_connect_primary,
- context);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_connect_primary_again,
+ context, 0, 0);
return;
}
/* Unref */
- silc_socket_free(backup_router);
+ silc_packet_stream_unref(backup_router);
if (!backup_router->protocol)
return;
silc_socket_free(ctx->sock); /* unref */
ctx->sock = silc_socket_dup(server_entry->connection);
backup_router->protocol = NULL;
+#endif /* 0 */x
}
/* Timeout callback used by the backup router to send the ENDING packet
SILC_TASK_CALLBACK(silc_server_backup_send_resumed)
{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerBackupProtocolContext ctx = protocol->context;
+#if 0
+ SilcServerBackupProtocolContext ctx = context;
SilcServer server = ctx->server;
unsigned char data[2];
int i;
data[0] = SILC_SERVER_BACKUP_ENDING;
data[1] = ctx->session;
silc_server_packet_send(server, ctx->sock, SILC_PACKET_RESUME_ROUTER, 0,
- data, sizeof(data), FALSE);
+ data, sizeof(data));
/* The protocol will go to END state. */
protocol->state = SILC_PROTOCOL_STATE_END;
+#endif /* 0 */
}
/* Backup resuming protocol. This protocol is executed when the primary
router wants to resume its position as being primary router. */
-SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
+SILC_TASK_CALLBACK(silc_server_protocol_backup)
{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerBackupProtocolContext ctx = protocol->context;
+#if 0
+ SilcServerBackupProtocolContext ctx = context;
SilcServer server = ctx->server;
SilcServerEntry server_entry;
- SilcSocketConnection sock = NULL;
+ SilcPacketStream sock = NULL;
unsigned char data[2];
int i;
sock = server->sockets[i];
if (!sock || !sock->user_data ||
sock->user_data == server->id_entry ||
- (sock->type != SILC_SOCKET_TYPE_ROUTER &&
- sock->type != SILC_SOCKET_TYPE_SERVER))
+ (sock->type != SILC_CONN_ROUTER &&
+ sock->type != SILC_CONN_SERVER))
continue;
server_entry = sock->user_data;
silc_net_is_ip(primary->host) ?
NULL : primary->host,
primary->port,
- SILC_SOCKET_TYPE_ROUTER)) {
+ SILC_CONN_ROUTER)) {
SILC_LOG_DEBUG(("Received START (session %d), reconnect to router",
ctx->session));
- silc_server_backup_reconnect(server,
- primary->host, primary->port,
- silc_server_backup_connect_primary,
- silc_socket_dup(ctx->sock));
+ silc_server_create_connection(server, FALSE;
+ primary->host, primary->port,
+ silc_server_backup_connect_primary,
+ silc_socket_dup(ctx->sock));
} else {
/* Nowhere to connect just return the CONNECTED packet */
SILC_LOG_DEBUG(("Received START (session %d), send CONNECTED back",
sock = server->sockets[i];
if (!sock || !sock->user_data ||
sock->user_data == server->id_entry ||
- (sock->type != SILC_SOCKET_TYPE_ROUTER &&
- sock->type != SILC_SOCKET_TYPE_SERVER))
+ (sock->type != SILC_CONN_ROUTER &&
+ sock->type != SILC_CONN_SERVER))
continue;
/* Send to backup last */
data[1] = 0;
silc_server_packet_send(server, sock, SILC_PACKET_RESUME_ROUTER, 0,
data, sizeof(data), FALSE);
- silc_server_packet_queue_purge(server, sock);
}
/* Now send the same packet to backup */
case SILC_PROTOCOL_STATE_UNKNOWN:
break;
}
+#endif /* 0 */
}
/* Final resuming protocol completion callback */
SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerBackupProtocolContext ctx = protocol->context;
+#if 0
+ SilcServerBackupProtocolContext ctx = context;
SilcServer server = ctx->server;
SilcServerEntry server_entry;
- SilcSocketConnection sock;
- bool error;
+ SilcPacketStream sock;
+ SilcBool error;
int i;
silc_schedule_task_del_by_context(server->schedule, protocol);
- error = (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
- protocol->state == SILC_PROTOCOL_STATE_FAILURE);
+ error = ctx->error;
if (error) {
SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
for (i = 0; i < server->config->param.connections_max; i++) {
sock = server->sockets[i];
if (!sock || !sock->user_data ||
- (sock->type != SILC_SOCKET_TYPE_ROUTER &&
- sock->type != SILC_SOCKET_TYPE_SERVER))
+ (sock->type != SILC_CONN_ROUTER &&
+ sock->type != SILC_CONN_SERVER))
continue;
server_entry = sock->user_data;
/* The SilcProtocol context was shared between all connections, clear
it from all connections. */
if (sock->protocol == protocol) {
- silc_server_packet_queue_purge(server, sock);
sock->protocol = NULL;
if (error) {
silc_protocol_free(protocol);
silc_free(ctx->sessions);
silc_free(ctx);
+#endif /* 0 */
}
SILC_TASK_CALLBACK(silc_server_backup_announce_watches)
{
- SilcSocketConnection sock = context;
+#if 0
+ SilcPacketStream sock = context;
SilcServer server = app_context;
if (sock->users > 1)
silc_server_announce_watches(server, sock);
silc_socket_free(sock);
+#endif /* 0 */
}
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2003 Pekka Riikonen
+ Copyright (C) 2001 - 2003, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
will become unresponsive. If `local' is TRUE then the `backup_server' is
in the local cell, if FALSE it is in some other cell. */
void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
- const char *ip, int port, bool local);
+ const char *ip, int port, SilcBool local);
/* Returns backup router for IP and port in `server_id' or NULL if there
does not exist backup router. */
replaced by an backup router. If it has been then this returns TRUE
and the bacup router entry to the `server' pointer if non-NULL. Returns
FALSE if the router is not replaced by backup router. */
-bool silc_server_backup_replaced_get(SilcServer server,
+SilcBool silc_server_backup_replaced_get(SilcServer server,
SilcServerID *server_id,
SilcServerEntry *server_entry);
That is why all backup routers need to get this data too. It is expected
that the caller already knows that the `packet' is broadcast packet. */
void silc_server_backup_broadcast(SilcServer server,
- SilcSocketConnection sender,
- SilcPacketContext *packet);
+ SilcPacketStream sender,
+ SilcPacket packet);
/* A generic routine to send data to all backup routers. If the `sender'
is provided it will indicate the original sender of the packet and the
SilcPacketFlags flags,
unsigned char *data,
SilcUInt32 data_len,
- bool force_send,
- bool local);
+ SilcBool force_send,
+ SilcBool local);
/* Same as silc_server_backup_send but sets a specific Destination ID to
the packet. The Destination ID is indicated by the `dst_id' and the
SilcIdType dst_id_type,
unsigned char *data,
SilcUInt32 data_len,
- bool force_send,
- bool local);
+ SilcBool force_send,
+ SilcBool local);
/* Send the START_USE indication to remote connection. If `failure' is
TRUE then this sends SILC_PACKET_FAILURE. Otherwise it sends
SILC_PACKET_RESUME_ROUTER. */
void silc_server_backup_send_start_use(SilcServer server,
- SilcSocketConnection sock,
- bool failure);
+ SilcPacketStream sock,
+ SilcBool failure);
/* Send the REPLACED indication to remote router. This is send by the
primary router (remote router) of the primary router that came back
online. This is not sent by backup router or any other server. */
void silc_server_backup_send_replaced(SilcServer server,
- SilcSocketConnection sock);
+ SilcPacketStream sock);
/* Processes incoming RESUME_ROUTER packet. This can give the packet
for processing to the protocol handler or allocate new protocol if
start command is received. */
void silc_server_backup_resume_router(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet);
-
-/* Constantly tries to reconnect to a primary router indicated by the
- `ip' and `port'. The `connected' callback will be called when the
- connection is created. */
-void silc_server_backup_reconnect(SilcServer server,
- const char *ip, SilcUInt16 port,
- SilcServerConnectRouterCallback callback,
- void *context);
+ SilcPacketStream sock,
+ SilcPacket packet);
/* Called when we've established connection back to our primary router
when we've acting as backup router and have replaced the primary router
/* Backup resuming protocol. This protocol is executed when the primary
router wants to resume its position as being primary router. */
-SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup);
+SILC_TASK_CALLBACK(silc_server_protocol_backup);
#endif /* SERVER_BACKUP_H */
*/
struct SilcServerStruct {
char *server_name;
- int sock;
SilcServerEntry id_entry;
SilcServerID *id;
unsigned char *id_string;
unsigned int server_shutdown: 1; /* Set when shutting down */
unsigned int no_reconnect : 1; /* If set, server won't reconnect to
router after disconnection. */
+ unsigned int no_conf : 1; /* Set when connecting without
+ configuration. */
SilcServerEntry router; /* Pointer to the primary router */
unsigned long router_connect; /* Time when router was connected */
SilcHashTable watcher_list;
SilcHashTable watcher_list_pk;
+ SilcDList listeners; /* TCP listeners */
+ SilcPacketEngine packet_engine; /* Packet engine */
+ SilcDList conns;
+ SilcSKR repository;
+
/* Table of connected sockets */
- SilcSocketConnection *sockets;
+ SilcPacketStream *sockets;
/* Server public key */
- SilcPKCS pkcs;
SilcPublicKey public_key;
SilcPrivateKey private_key;
SilcIDListPurge purge_i;
SilcIDListPurge purge_g;
-#ifdef SILC_SIM
- /* SIM (SILC Module) list */
- SilcDList sim;
-#endif
-
/* Hash table for public keys of all clients */
SilcHashTable pk_hash;
};
Failure packets are processed with timeout and data is saved in this
structure. */
typedef struct {
- SilcSocketConnection sock;
+ SilcPacketStream sock;
SilcUInt32 failure;
} *SilcServerFailureContext;
#define SILC_GET_SKE_FLAGS(x, p) \
if ((x)) { \
if ((x)->param && (x)->param->key_exchange_pfs) \
- (p)->flags |= SILC_SKE_SP_FLAG_PFS; \
+ (p) |= SILC_SKE_SP_FLAG_PFS; \
if (!(x)->publickeys) \
- (p)->flags |= SILC_SKE_SP_FLAG_MUTUAL; \
+ (p) |= SILC_SKE_SP_FLAG_MUTUAL; \
}
+#define SILC_CONNTYPE_STRING(ctype) \
+ (ctype == SILC_CONN_CLIENT ? "Client" : \
+ ctype == SILC_CONN_SERVER ? "Server" : \
+ ctype == SILC_CONN_ROUTER ? "Router" : "Unknown")
+
/* Prototypes */
-SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_final);
-SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_callback);
-SILC_TASK_CALLBACK_GLOBAL(silc_server_connect_to_router);
+SILC_TASK_CALLBACK(silc_server_rekey_final);
+SILC_TASK_CALLBACK(silc_server_rekey_callback);
+SILC_TASK_CALLBACK(silc_server_connect_to_router);
void silc_server_watcher_list_destroy(void *key, void *context,
void *user_context);
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2002 - 2005 Pekka Riikonen
+ Copyright (C) 2002 - 2005, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "server_internal.h"
typedef struct {
- SilcSocketConnection sock; /* Connection of this query */
+ SilcPacketStream sock; /* Connection of this query */
unsigned char **arg; /* Query argument */
SilcUInt32 *arg_lens; /* Query argument lengths */
SilcUInt32 *arg_types; /* Query argument types */
/* Query session context */
typedef struct {
/* Queried data */
- char *nickname; /* Queried nickname, normalized */
- char *nick_server; /* Queried nickname's server */
+ char nickname[128 + 1]; /* Queried nickname, normalized */
+ char nick_server[128 + 1]; /* Queried nickname's server */
char *server_name; /* Queried server name, normalized */
char *channel_name; /* Queried channel name, normalized */
SilcServerQueryID ids; /* Queried IDs */
void silc_server_query_send_router_reply(void *context, void *reply);
void silc_server_query_parse(SilcServer server, SilcServerQuery query);
void silc_server_query_process(SilcServer server, SilcServerQuery query,
- bool resolve);
+ SilcBool resolve);
void silc_server_query_resolve(SilcServer server, SilcServerQuery query,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcClientEntry client_entry);
void silc_server_query_resolve_reply(void *context, void *reply);
void silc_server_query_send_reply(SilcServer server,
silc_free(query->queries[i].id);
silc_free(query->queries);
- silc_free(query->nickname);
- silc_free(query->nick_server);
silc_free(query->server_name);
silc_free(query->channel_name);
to the entity who sent this query to us automatically. Returns
TRUE if the query is being processed or FALSE on error. */
-bool silc_server_query_command(SilcServer server, SilcCommand querycmd,
+SilcBool silc_server_query_command(SilcServer server, SilcCommand querycmd,
SilcServerCommandContext cmd)
{
SilcServerQuery query;
silc_server_packet_send(server,
SILC_PRIMARY_ROUTE(server),
SILC_PACKET_COMMAND, 0,
- tmpbuf->data, tmpbuf->len, TRUE);
+ tmpbuf->data, silc_buffer_len(tmpbuf));
silc_command_set_ident(query->cmd->payload, old_ident);
silc_buffer_free(tmpbuf);
SILC_LOG_DEBUG(("Received reply from router to query"));
/* If the original command caller has gone away, just stop. */
- if (query->cmd->sock->users == 1) {
+ if (!silc_packet_stream_is_valid(query->cmd->sock)) {
SILC_LOG_DEBUG(("Original command caller vanished"));
silc_server_query_free(query);
return;
buffer = silc_command_payload_encode_payload(cmdr->payload);
silc_server_packet_send(server, query->cmd->sock,
SILC_PACKET_COMMAND_REPLY, 0,
- buffer->data, buffer->len, FALSE);
+ buffer->data, silc_buffer_len(buffer));
silc_buffer_free(buffer);
silc_server_query_free(query);
return;
void silc_server_query_parse(SilcServer server, SilcServerQuery query)
{
SilcServerCommandContext cmd = query->cmd;
+ SilcIDListData idata = silc_packet_get_context(cmd->sock);
unsigned char *tmp;
SilcUInt32 tmp_len, argc = silc_argument_get_arg_num(cmd->args);
- void *id;
- SilcIdType id_type;
+ SilcID id;
int i;
SILC_LOG_DEBUG(("Parsing %s query",
/* When Requested Attributes is present we will assure that this
client cannot execute the WHOIS command too fast. This would be
same as having SILC_CF_LAG_STRICT. */
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
- cmd->sock->user_data)
- ((SilcClientEntry)cmd->sock->user_data)->fast_command = 6;
+ if (idata && idata->conn_type == SILC_CONN_CLIENT)
+ ((SilcClientEntry)idata)->fast_command = 6;
}
/* Get Client IDs if present. Take IDs always instead of nickname. */
/* Get the nickname@server string and parse it */
if (tmp && ((tmp_len > 128) ||
- !silc_parse_userfqdn(tmp, &query->nickname, &query->nick_server))) {
+ !silc_parse_userfqdn(tmp, query->nickname,
+ sizeof(query->nickname),
+ query->nick_server,
+ sizeof(query->nick_server)))) {
silc_server_query_send_error(server, query,
SILC_STATUS_ERR_BAD_NICKNAME, 0);
silc_server_query_free(query);
silc_server_query_free(query);
return;
}
- silc_free(query->nickname);
- query->nickname = tmp;
+ memset(query->nickname, 0, sizeof(query->nickname));
+ silc_snprintf(query->nickname, sizeof(query->nickname), "%s", tmp);
+ silc_free(tmp);
}
} else {
if (!tmp)
continue;
- id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
- if (!id || id_type != SILC_ID_CLIENT) {
+ if (!silc_id_payload_parse_id(tmp, tmp_len, &id) ||
+ id.type != SILC_ID_CLIENT) {
silc_server_query_add_error(server, query, 1, i + 4,
SILC_STATUS_ERR_BAD_CLIENT_ID);
continue;
send the query to router, unless done so already */
if (server->server_type == SILC_SERVER && !query->resolved) {
if (!silc_idlist_find_client_by_id(server->local_list,
- id, TRUE, NULL)) {
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT ||
+ &id.u.client_id, TRUE, NULL)) {
+ if (idata->conn_type != SILC_CONN_CLIENT ||
!silc_idlist_find_client_by_id(server->global_list,
- id, TRUE, NULL)) {
+ &id.u.client_id, TRUE, NULL)) {
silc_server_query_send_router(server, query);
for (i = 0; i < query->ids_count; i++)
silc_free(query->ids[i].id);
silc_free(query->ids);
query->ids = NULL;
query->ids_count = 0;
- silc_free(id);
return;
}
}
}
- query->ids[query->ids_count].id = id;
+ query->ids[query->ids_count].id = silc_id_dup(&id.u.client_id,
+ SILC_ID_CLIENT);
query->ids[query->ids_count].id_type = SILC_ID_CLIENT;
query->ids_count++;
}
/* Get the nickname@server string and parse it */
if (tmp_len > 128 ||
- !silc_parse_userfqdn(tmp, &query->nickname, &query->nick_server)) {
+ !silc_parse_userfqdn(tmp, query->nickname, sizeof(query->nickname),
+ query->nick_server, sizeof(query->nick_server))) {
silc_server_query_send_error(server, query,
SILC_STATUS_ERR_BAD_NICKNAME, 0);
silc_server_query_free(query);
silc_server_query_free(query);
return;
}
- silc_free(query->nickname);
- query->nickname = tmp;
+ memset(query->nickname, 0, sizeof(query->nickname));
+ silc_snprintf(query->nickname, sizeof(query->nickname), "%s", tmp);
+ silc_free(tmp);
/* Get the max count of reply messages allowed */
tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
if (tmp) {
/* Get the nickname@server string and parse it */
if (tmp_len > 128 ||
- !silc_parse_userfqdn(tmp, &query->nickname, &query->nick_server))
+ !silc_parse_userfqdn(tmp, query->nickname,
+ sizeof(query->nickname),
+ query->nick_server,
+ sizeof(query->nick_server)))
silc_server_query_add_error(server, query, 1, 1,
SILC_STATUS_ERR_BAD_NICKNAME);
silc_server_query_free(query);
return;
}
- silc_free(query->nickname);
- query->nickname = tmp;
+ memset(query->nickname, 0, sizeof(query->nickname));
+ silc_snprintf(query->nickname, sizeof(query->nickname), "%s", tmp);
+ silc_free(tmp);
}
/* Try get server name */
query->channel_name = tmp;
}
- if (!query->nickname && !query->server_name && !query->channel_name) {
+ if (!query->nickname[0] && !query->server_name && !query->channel_name) {
silc_server_query_send_error(server, query,
SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
silc_server_query_free(query);
if (!tmp)
continue;
- id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
- if (!id) {
+ if (!silc_id_payload_parse_id(tmp, tmp_len, &id)) {
silc_server_query_add_error(server, query, 1, i + 5,
SILC_STATUS_ERR_BAD_CLIENT_ID);
continue;
/* Normal server must check whether this ID exist, and if not then
send the query to router, unless done so already */
if (server->server_type == SILC_SERVER && !query->resolved) {
- if (id_type == SILC_ID_CLIENT) {
+ if (id.type == SILC_ID_CLIENT) {
if (!silc_idlist_find_client_by_id(server->local_list,
- id, TRUE, NULL)) {
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT ||
+ &id.u.client_id, TRUE, NULL)) {
+ if (idata->conn_type != SILC_CONN_CLIENT ||
!silc_idlist_find_client_by_id(server->global_list,
- id, TRUE, NULL)) {
+ &id.u.client_id, TRUE,
+ NULL)) {
silc_server_query_send_router(server, query);
for (i = 0; i < query->ids_count; i++)
silc_free(query->ids[i].id);
silc_free(query->ids);
query->ids = NULL;
query->ids_count = 0;
- silc_free(id);
return;
}
}
silc_free(query->ids);
query->ids = NULL;
query->ids_count = 0;
- silc_free(id);
return;
}
}
- query->ids[query->ids_count].id = id;
- query->ids[query->ids_count].id_type = id_type;
+ if (id.type == SILC_ID_CLIENT)
+ query->ids[query->ids_count].id = silc_id_dup(&id.u.client_id,
+ SILC_ID_CLIENT);
+ if (id.type == SILC_ID_SERVER)
+ query->ids[query->ids_count].id = silc_id_dup(&id.u.server_id,
+ SILC_ID_SERVER);
+ if (id.type == SILC_ID_CHANNEL)
+ query->ids[query->ids_count].id = silc_id_dup(&id.u.channel_id,
+ SILC_ID_CHANNEL);
+ query->ids[query->ids_count].id_type = id.type;
query->ids_count++;
}
}
typedef struct {
SilcClientEntry **clients;
SilcUInt32 *clients_count;
- bool found;
+ SilcBool found;
} *SilcServerPublicKeyUser, SilcServerPublicKeyUserStruct;
void silc_server_public_key_hash_foreach(void *key, void *context,
SilcAttribute attribute;
SilcAttributeObjPk pk;
SilcPublicKey publickey;
+ SilcPKCSType type;
+ SilcBool found = FALSE, no_clients = FALSE;
int i;
- bool found = FALSE, no_clients = FALSE;
/* If no clients were found, we only check the attributes
if the user wasn't searching for nickname/ids */
if (!(*clients)) {
no_clients = TRUE;
- if (query->nickname || query->ids_count)
+ if (query->nickname[0] || query->ids_count)
return;
}
if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
continue;
- if (!silc_pkcs_public_key_decode(pk.data, pk.data_len,
- &publickey)) {
+ if (!strcmp(pk.type, "silc-rsa"))
+ type = SILC_PKCS_SILC;
+ else if (!strcmp(pk.type, "ssh-rsa"))
+ type = SILC_PKCS_SSH2;
+ else if (!strcmp(pk.type, "x509v3-sign-rsa"))
+ type = SILC_PKCS_X509V3;
+ else if (!strcmp(pk.type, "pgp-sign-rsa"))
+ type = SILC_PKCS_OPENPGP;
+ else
+ continue;
+
+ if (!silc_pkcs_public_key_alloc(type, pk.data, pk.data_len,
+ &publickey)) {
silc_free(pk.type);
silc_free(pk.data);
continue;
}
}
- if (!found && !query->nickname && !query->ids)
+ if (!found && !query->nickname[0] && !query->ids)
silc_server_query_add_error(server, query, 2, 0,
SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
}
sender of the query command. */
void silc_server_query_process(SilcServer server, SilcServerQuery query,
- bool resolve)
+ SilcBool resolve)
{
SilcServerCommandContext cmd = query->cmd;
- bool check_global = FALSE;
+ SilcIDListData idata = silc_packet_get_context(cmd->sock);
+ SilcBool check_global = FALSE;
void *entry;
SilcClientEntry *clients = NULL, client_entry;
SilcChannelEntry *channels = NULL;
/* Check global lists if query is coming from client or we are not
normal server (we know global information). */
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
+ if (idata->conn_type == SILC_CONN_CLIENT)
check_global = TRUE;
else if (server->server_type != SILC_SERVER)
check_global = TRUE;
- if (query->nickname) {
+ if (query->nickname[0]) {
/* Get all clients matching nickname from local list */
if (!silc_idlist_get_clients_by_hash(server->local_list,
query->nickname, server->md5hash,
silc_idlist_get_clients_by_nickname(server->local_list,
query->nickname,
query->nick_server,
+ /* XXX nick_server may not be set */
&clients, &clients_count);
/* Check global list as well */
silc_idlist_get_clients_by_nickname(server->global_list,
query->nickname,
query->nick_server,
+ /* XXX nick_server may not be set */
&clients, &clients_count);
}
client entry calls this function to do the resolving. */
void silc_server_query_resolve(SilcServer server, SilcServerQuery query,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcClientEntry client_entry)
{
SilcServerCommandContext cmd = query->cmd;
r->argc, r->arg, r->arg_lens,
r->arg_types, r->ident);
silc_server_packet_send(server, r->sock, SILC_PACKET_COMMAND, 0,
- res_cmd->data, res_cmd->len, FALSE);
+ res_cmd->data, silc_buffer_len(res_cmd));
silc_buffer_free(res_cmd);
/* Reprocess this packet after received reply */
/* Add the client entry to be resolved */
idp = silc_id_payload_encode(client_entry->id, SILC_ID_CLIENT);
- r->arg[r->argc] = silc_memdup(idp->data, idp->len);
- r->arg_lens[r->argc] = idp->len;
+ r->arg[r->argc] = silc_memdup(idp->data, silc_buffer_len(idp));
+ r->arg_lens[r->argc] = silc_buffer_len(idp);
r->arg_types[r->argc] = r->argc + 4;
r->argc++;
silc_buffer_free(idp);
SILC_LOG_DEBUG(("Reprocess the query"));
/* If the original command caller has gone away, just stop. */
- if (query->cmd->sock->users == 1) {
+ if (!silc_packet_stream_is_valid(query->cmd->sock)) {
SILC_LOG_DEBUG(("Original command caller vanished"));
silc_server_query_free(query);
return;
SilcUInt32 channels_count)
{
SilcServerCommandContext cmd = query->cmd;
+ SilcIDListData idata = silc_packet_get_context(cmd->sock);
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
SilcStatus status;
unsigned char *tmp;
SilcBuffer idp;
int i, k, valid_count;
char nh[384], uh[384];
- bool sent_reply = FALSE;
+ SilcBool sent_reply = FALSE;
SILC_LOG_DEBUG(("Sending reply to query"));
SILC_LOG_DEBUG(("Sending %d clients", clients_count));
/* Send clients */
if (clients_count) {
SilcClientEntry entry;
- SilcSocketConnection hsock;
+ SilcPacketStream hsock;
/* Mark all invalid entries */
for (i = 0, valid_count = 0; i < clients_count; i++) {
if (!strchr(entry->username, '@') && entry->connection) {
hsock = entry->connection;
silc_strncat(uh, sizeof(uh), "@", 1);
- len = strlen(hsock->hostname);
- silc_strncat(uh, sizeof(uh), hsock->hostname, len);
+ silc_socket_stream_get_info(hsock, NULL, (const char **)&tmp,
+ NULL, NULL);
+ silc_strncat(uh, sizeof(uh), tmp, strlen(tmp));
}
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
+ if (idata->conn_type == SILC_CONN_CLIENT)
channels =
silc_server_get_client_channel_list(server, entry, FALSE,
FALSE, &umode_list);
/* Send command reply */
silc_server_send_command_reply(server, cmd->sock, query->querycmd,
status, 0, ident, 10,
- 2, idp->data, idp->len,
+ 2, idp->data, silc_buffer_len(idp),
3, nh, strlen(nh),
4, uh, strlen(uh),
5, entry->userinfo,
strlen(entry->userinfo),
6, channels ? channels->data : NULL,
- channels ? channels->len : 0,
+ channels ? silc_buffer_len(channels)
+ : 0,
7, mode, 4,
8, idle, 4,
9, fingerprint,
fingerprint ? 20 : 0,
10, umode_list ? umode_list->data :
- NULL, umode_list ? umode_list->len :
+ NULL, umode_list ?
+ silc_buffer_len(umode_list) :
0, 11, attrs, len);
sent_reply = TRUE;
if (!entry->username) {
silc_server_send_command_reply(server, cmd->sock, query->querycmd,
status, 0, ident, 2,
- 2, idp->data, idp->len,
+ 2, idp->data, silc_buffer_len(idp),
3, nh, strlen(nh));
sent_reply = TRUE;
} else {
if (!strchr(entry->username, '@') && entry->connection) {
hsock = entry->connection;
silc_strncat(uh, sizeof(uh), "@", 1);
- len = strlen(hsock->hostname);
- silc_strncat(uh, sizeof(uh), hsock->hostname, len);
+ silc_socket_stream_get_info(hsock, NULL, (const char **)&tmp,
+ NULL, NULL);
+ silc_strncat(uh, sizeof(uh), tmp, strlen(tmp));
}
silc_server_send_command_reply(server, cmd->sock, query->querycmd,
status, 0, ident, 3,
- 2, idp->data, idp->len,
+ 2, idp->data, silc_buffer_len(idp),
3, nh, strlen(nh),
4, uh, strlen(uh));
sent_reply = TRUE;
/* Send command reply */
silc_server_send_command_reply(server, cmd->sock, query->querycmd,
status, 0, ident, 4,
- 2, idp->data, idp->len,
+ 2, idp->data, silc_buffer_len(idp),
3, nh, strlen(nh),
4, uh, strlen(uh),
5, entry->userinfo,
/* Not one valid entry was found, send error. If nickname was used
in query send error based on that, otherwise the query->errors
already includes proper errors. */
- if (query->nickname || (!query->ids && query->attrs))
+ if (query->nickname[0] || (!query->ids && query->attrs))
silc_server_query_add_error(server, query, 1, 1,
SILC_STATUS_ERR_NO_SUCH_NICK);
idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_IDENTIFY,
status, 0, ident, 2,
- 2, idp->data, idp->len,
+ 2, idp->data, silc_buffer_len(idp),
3, entry->server_name,
entry->server_name ?
strlen(entry->server_name) : 0);
idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_IDENTIFY,
status, 0, ident, 2,
- 2, idp->data, idp->len,
+ 2, idp->data, silc_buffer_len(idp),
3, entry->channel_name,
entry->channel_name ?
strlen(entry->channel_name) : 0);
silc_id_payload_encode(query->ids[query->errors[i].index].id,
query->ids[query->errors[k].index].id_type);
tmp = idp->data;
- len = idp->len;
+ len = silc_buffer_len(idp);
type = 2;
} else {
/* Take added ID. */
idp = silc_id_payload_encode(query->errors[i].id,
query->errors[k].id_type);
tmp = idp->data;
- len = idp->len;
+ len = silc_buffer_len(idp);
type = 2;
}
/* Finally compute the digital signature of all the data we provided
as an indication that we provided rightfull information, and this
also authenticates our public key. */
- if (silc_pkcs_get_key_len(server->pkcs) / 8 <= sizeof(sign) -1 &&
- silc_pkcs_sign_with_hash(server->pkcs, server->sha1hash,
- buffer->data, buffer->len,
- sign, &sign_len)) {
+ if (silc_pkcs_private_key_get_len(server->private_key) / 8 <=
+ sizeof(sign) -1 &&
+ silc_pkcs_sign(server->private_key, buffer->data,
+ silc_buffer_len(buffer), sign, sizeof(sign), &sign_len,
+ TRUE, server->sha1hash)) {
pk.type = NULL;
pk.data = sign;
pk.data_len = sign_len;
SilcClientEntry silc_server_query_client(SilcServer server,
const SilcClientID *client_id,
- bool always_resolve,
- bool *resolved)
+ SilcBool always_resolve,
+ SilcBool *resolved)
{
SilcClientEntry client;
idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
buffer = silc_command_payload_encode_va(SILC_COMMAND_WHOIS,
server->cmd_ident, 1,
- 4, idp->data, idp->len);
+ 4, idp->data,
+ silc_buffer_len(idp));
silc_server_packet_send(server, client ? client->router->connection :
SILC_PRIMARY_ROUTE(server),
SILC_PACKET_COMMAND, 0,
- buffer->data, buffer->len, FALSE);
+ buffer->data, silc_buffer_len(buffer));
silc_buffer_free(idp);
silc_buffer_free(buffer);
/*
- server_query.h
+ server_query.h
Author: Pekka Riikonen <priikone@silcnet.org>
SILC_COMMAND_IDENTIFY. This function handles the reply sending
to the entity who sent this query to us automatically. Returns
TRUE if the query is being processed or FALSE on error. */
-bool silc_server_query_command(SilcServer server, SilcCommand querycmd,
- SilcServerCommandContext cmd);
+SilcBool silc_server_query_command(SilcServer server, SilcCommand querycmd,
+ SilcServerCommandContext cmd);
/* Find client by the Client ID indicated by the `client_id', and if not
found then query it by using WHOIS command. The client information
function. The server->cmd_ident includes the query identifier. */
SilcClientEntry silc_server_query_client(SilcServer server,
const SilcClientID *client_id,
- bool always_resolve,
- bool *resolved);
+ SilcBool always_resolve,
+ SilcBool *resolved);
#endif /* SERVER_QUERY_H */
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2005, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
too. If `server_signoff' is TRUE then SERVER_SIGNOFF notify is
distributed to our local clients. */
-bool silc_server_remove_clients_by_server(SilcServer server,
- SilcServerEntry router,
- SilcServerEntry entry,
- bool server_signoff)
+SilcBool silc_server_remove_clients_by_server(SilcServer server,
+ SilcServerEntry router,
+ SilcServerEntry entry,
+ SilcBool server_signoff)
{
- SilcIDCacheList list = NULL;
+ SilcList list;
SilcIDCacheEntry id_cache = NULL;
SilcClientEntry client = NULL;
SilcBuffer idp;
argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
- argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
- memcpy(argv[argc], idp->data, idp->len);
- argv_lens[argc] = idp->len;
+ argv[argc] = silc_calloc(silc_buffer_len(idp), sizeof(*argv[0]));
+ memcpy(argv[argc], idp->data, silc_buffer_len(idp));
+ argv_lens[argc] = silc_buffer_len(idp);
argv_types[argc] = argc + 1;
argc++;
silc_buffer_free(idp);
}
if (silc_idcache_get_all(server->local_list->clients, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- client = (SilcClientEntry)id_cache->context;
-
- /* If client is not registered, is not originated from `router'
- and is not owned by `entry', skip it. */
- if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
- client->router != router ||
- (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
- client->id->ip.data_len))) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- else
- continue;
- }
-
- if (server_signoff) {
- idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
- argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
- argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
- (argc + 1));
- argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
- (argc + 1));
- argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
- memcpy(argv[argc], idp->data, idp->len);
- argv_lens[argc] = idp->len;
- argv_types[argc] = argc + 1;
- argc++;
- silc_buffer_free(idp);
- }
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ client = (SilcClientEntry)id_cache->context;
+
+ /* If client is not registered, is not originated from `router'
+ and is not owned by `entry', skip it. */
+ if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
+ client->router != router ||
+ (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
+ client->id->ip.data_len))) {
+ continue;
+ }
- /* Update statistics */
- server->stat.clients--;
- if (server->stat.cell_clients)
- server->stat.cell_clients--;
- SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
- SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
-
- if (client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- client->data.public_key,
- client);
- silc_server_remove_clients_channels(server, entry, clients,
- client, channels);
- silc_server_del_from_watcher_list(server, client);
-
- /* Remove the client entry */
- if (!server_signoff) {
- client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
- client->mode = 0;
- client->router = NULL;
- client->connection = NULL;
- id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
- } else {
- silc_idlist_del_data(client);
- silc_idlist_del_client(server->local_list, client);
- }
+ if (server_signoff) {
+ idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+ argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
+ argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
+ (argc + 1));
+ argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
+ (argc + 1));
+ argv[argc] = silc_calloc(silc_buffer_len(idp), sizeof(*argv[0]));
+ memcpy(argv[argc], idp->data, silc_buffer_len(idp));
+ argv_lens[argc] = silc_buffer_len(idp);
+ argv_types[argc] = argc + 1;
+ argc++;
+ silc_buffer_free(idp);
+ }
- if (!silc_idcache_list_next(list, &id_cache))
- break;
+ /* Update statistics */
+ server->stat.clients--;
+ if (server->stat.cell_clients)
+ server->stat.cell_clients--;
+ SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
+ SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
+
+ if (client->data.public_key)
+ silc_hash_table_del_by_context(server->pk_hash,
+ client->data.public_key,
+ client);
+ silc_server_remove_clients_channels(server, entry, clients,
+ client, channels);
+ silc_server_del_from_watcher_list(server, client);
+
+ /* Remove the client entry */
+ if (!server_signoff) {
+ client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+ client->mode = 0;
+ client->router = NULL;
+ client->connection = NULL;
+ } else {
+ silc_idlist_del_data(client);
+ silc_idlist_del_client(server->local_list, client);
}
}
- silc_idcache_list_free(list);
}
if (silc_idcache_get_all(server->global_list->clients, &list)) {
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ client = (SilcClientEntry)id_cache->context;
+
+ /* If client is not registered, is not originated from `router'
+ and is not owned by `entry', skip it. */
+ if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
+ client->router != router ||
+ (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
+ client->id->ip.data_len))) {
+ continue;
+ }
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- client = (SilcClientEntry)id_cache->context;
-
- /* If client is not registered, is not originated from `router'
- and is not owned by `entry', skip it. */
- if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
- client->router != router ||
- (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
- client->id->ip.data_len))) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- else
- continue;
- }
-
- if (server_signoff) {
- idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
- argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
- argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
- (argc + 1));
- argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
- (argc + 1));
- argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
- memcpy(argv[argc], idp->data, idp->len);
- argv_lens[argc] = idp->len;
- argv_types[argc] = argc + 1;
- argc++;
- silc_buffer_free(idp);
- }
-
- /* Update statistics */
- server->stat.clients--;
- if (server->stat.cell_clients)
- server->stat.cell_clients--;
- SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
- SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
-
- if (client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- client->data.public_key,
- client);
- silc_server_remove_clients_channels(server, entry, clients,
- client, channels);
- silc_server_del_from_watcher_list(server, client);
-
- /* Remove the client entry */
- if (!server_signoff) {
- client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
- client->mode = 0;
- client->router = NULL;
- client->connection = NULL;
- id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
- } else {
- silc_idlist_del_data(client);
- silc_idlist_del_client(server->global_list, client);
- }
+ if (server_signoff) {
+ idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+ argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
+ argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
+ (argc + 1));
+ argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
+ (argc + 1));
+ argv[argc] = silc_calloc(silc_buffer_len(idp), sizeof(*argv[0]));
+ memcpy(argv[argc], idp->data, silc_buffer_len(idp));
+ argv_lens[argc] = silc_buffer_len(idp);
+ argv_types[argc] = argc + 1;
+ argc++;
+ silc_buffer_free(idp);
+ }
- if (!silc_idcache_list_next(list, &id_cache))
- break;
+ /* Update statistics */
+ server->stat.clients--;
+ if (server->stat.cell_clients)
+ server->stat.cell_clients--;
+ SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
+ SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
+
+ if (client->data.public_key)
+ silc_hash_table_del_by_context(server->pk_hash,
+ client->data.public_key,
+ client);
+ silc_server_remove_clients_channels(server, entry, clients,
+ client, channels);
+ silc_server_del_from_watcher_list(server, client);
+
+ /* Remove the client entry */
+ if (!server_signoff) {
+ client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+ client->mode = 0;
+ client->router = NULL;
+ client->connection = NULL;
+ } else {
+ silc_idlist_del_data(client);
+ silc_idlist_del_client(server->global_list, client);
}
}
- silc_idcache_list_free(list);
}
/* Return now if we are shutting down */
argc, args);
silc_server_packet_send_clients(server, clients,
SILC_PACKET_NOTIFY, 0, FALSE,
- not->data, not->len, FALSE);
+ not->data, silc_buffer_len(not));
/* Send notify also to local backup routers */
silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
- not->data, not->len, FALSE, TRUE);
+ not->data, silc_buffer_len(not), FALSE, TRUE);
silc_buffer_free(args);
silc_buffer_free(not);
}
/* Do not send the channel key if private channel key mode is set */
- if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY || !channel->channel_key)
+ if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY || !channel->send_key)
continue;
silc_server_send_channel_key(server, NULL, channel,
SilcServerEntry from,
SilcServerEntry to,
SilcClientEntry client,
- bool local,
+ SilcBool local,
SilcIDCacheEntry client_cache)
{
SilcServerEntry server_entry;
SilcIDCacheEntry id_cache = NULL;
- SilcIDCacheList list;
- bool tolocal = (to == server->id_entry);
+ SilcList list;
+ SilcBool tolocal = (to == server->id_entry);
SILC_LOG_DEBUG(("Start"));
if (!silc_idcache_get_all(server->local_list->servers, &list))
return NULL;
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- server_entry = (SilcServerEntry)id_cache->context;
- if (server_entry != from &&
- (tolocal || server_entry != server->id_entry) &&
- SILC_ID_COMPARE(server_entry->id, client->id,
- client->id->ip.data_len)) {
- SILC_LOG_DEBUG(("Found (local) %s",
- silc_id_render(server_entry->id, SILC_ID_SERVER)));
-
- if (!server_entry->data.send_key && server_entry->router) {
- SILC_LOG_DEBUG(("Server not locally connected, use its router"));
- /* If the client is not marked as local then move it to local list
- since the server is local. */
- if (!local) {
- SILC_LOG_DEBUG(("Moving client to local list"));
- silc_idcache_add(server->local_list->clients, client_cache->name,
- client_cache->id, client_cache->context,
- client_cache->expire, NULL);
- silc_idcache_del_by_context(server->global_list->clients, client);
- }
- server_entry = server_entry->router;
- } else {
- SILC_LOG_DEBUG(("Server locally connected"));
- /* If the client is not marked as local then move it to local list
- since the server is local. */
- if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
- SILC_LOG_DEBUG(("Moving client to local list"));
- silc_idcache_add(server->local_list->clients, client_cache->name,
- client_cache->id, client_cache->context,
- client_cache->expire, NULL);
- silc_idcache_del_by_context(server->global_list->clients, client);
-
- } else if (server->server_type == SILC_BACKUP_ROUTER && local) {
- /* If we are backup router and this client is on local list, we
- must move it to global list, as it is not currently local to
- us (we are not primary). */
- SILC_LOG_DEBUG(("Moving client to global list"));
- silc_idcache_add(server->global_list->clients, client_cache->name,
- client_cache->id, client_cache->context,
- client_cache->expire, NULL);
- silc_idcache_del_by_context(server->local_list->clients, client);
- }
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ server_entry = (SilcServerEntry)id_cache->context;
+ if (server_entry != from &&
+ (tolocal || server_entry != server->id_entry) &&
+ SILC_ID_COMPARE(server_entry->id, client->id,
+ client->id->ip.data_len)) {
+ SILC_LOG_DEBUG(("Found (local) %s",
+ silc_id_render(server_entry->id, SILC_ID_SERVER)));
+
+ if (!SILC_IS_LOCAL(server_entry) && server_entry->router) {
+ SILC_LOG_DEBUG(("Server not locally connected, use its router"));
+ /* If the client is not marked as local then move it to local list
+ since the server is local. */
+ if (!local) {
+ SILC_LOG_DEBUG(("Moving client to local list"));
+ silc_idcache_add(server->local_list->clients, client_cache->name,
+ client_cache->id, client_cache->context);
+ silc_idcache_del_by_context(server->global_list->clients, client,
+ NULL);
+ }
+ server_entry = server_entry->router;
+ } else {
+ SILC_LOG_DEBUG(("Server locally connected"));
+ /* If the client is not marked as local then move it to local list
+ since the server is local. */
+ if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
+ SILC_LOG_DEBUG(("Moving client to local list"));
+ silc_idcache_add(server->local_list->clients, client_cache->name,
+ client_cache->id, client_cache->context);
+ silc_idcache_del_by_context(server->global_list->clients, client,
+ NULL);
+
+ } else if (server->server_type == SILC_BACKUP_ROUTER && local) {
+ /* If we are backup router and this client is on local list, we
+ must move it to global list, as it is not currently local to
+ us (we are not primary). */
+ SILC_LOG_DEBUG(("Moving client to global list"));
+ silc_idcache_add(server->global_list->clients, client_cache->name,
+ client_cache->id, client_cache->context);
+ silc_idcache_del_by_context(server->local_list->clients, client,
+ NULL);
}
-
- silc_idcache_list_free(list);
- return server_entry;
}
- if (!silc_idcache_list_next(list, &id_cache))
- break;
+ return server_entry;
}
}
- silc_idcache_list_free(list);
-
if (!silc_idcache_get_all(server->global_list->servers, &list))
return NULL;
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- server_entry = (SilcServerEntry)id_cache->context;
- if (server_entry != from && server_entry != server->id_entry &&
- (tolocal || server_entry != server->id_entry) &&
- SILC_ID_COMPARE(server_entry->id, client->id,
- client->id->ip.data_len)) {
- SILC_LOG_DEBUG(("Found (global) %s",
- silc_id_render(server_entry->id, SILC_ID_SERVER)));
-
- if (!server_entry->data.send_key && server_entry->router) {
- SILC_LOG_DEBUG(("Server not locally connected, use its router"));
- /* If the client is marked as local then move it to global list
- since the server is global. */
- if (local) {
- SILC_LOG_DEBUG(("Moving client to global list"));
- silc_idcache_add(server->global_list->clients, client_cache->name,
- client_cache->id, client_cache->context, 0, NULL);
- silc_idcache_del_by_context(server->local_list->clients, client);
- }
- server_entry = server_entry->router;
- } else {
- SILC_LOG_DEBUG(("Server locally connected"));
- /* If the client is marked as local then move it to global list
- since the server is global. */
- if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
- SILC_LOG_DEBUG(("Moving client to global list"));
- silc_idcache_add(server->global_list->clients, client_cache->name,
- client_cache->id, client_cache->context, 0, NULL);
- silc_idcache_del_by_context(server->local_list->clients, client);
- }
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ server_entry = (SilcServerEntry)id_cache->context;
+ if (server_entry != from && server_entry != server->id_entry &&
+ (tolocal || server_entry != server->id_entry) &&
+ SILC_ID_COMPARE(server_entry->id, client->id,
+ client->id->ip.data_len)) {
+ SILC_LOG_DEBUG(("Found (global) %s",
+ silc_id_render(server_entry->id, SILC_ID_SERVER)));
+
+ if (!SILC_IS_LOCAL(server_entry) && server_entry->router) {
+ SILC_LOG_DEBUG(("Server not locally connected, use its router"));
+ /* If the client is marked as local then move it to global list
+ since the server is global. */
+ if (local) {
+ SILC_LOG_DEBUG(("Moving client to global list"));
+ silc_idcache_add(server->global_list->clients, client_cache->name,
+ client_cache->id, client_cache->context);
+ silc_idcache_del_by_context(server->local_list->clients, client,
+ NULL);
+ }
+ server_entry = server_entry->router;
+ } else {
+ SILC_LOG_DEBUG(("Server locally connected"));
+ /* If the client is marked as local then move it to global list
+ since the server is global. */
+ if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
+ SILC_LOG_DEBUG(("Moving client to global list"));
+ silc_idcache_add(server->global_list->clients, client_cache->name,
+ client_cache->id, client_cache->context);
+ silc_idcache_del_by_context(server->local_list->clients, client,
+ NULL);
}
-
- silc_idcache_list_free(list);
- return server_entry;
}
-
- if (!silc_idcache_list_next(list, &id_cache))
- break;
+ return server_entry;
}
}
- silc_idcache_list_free(list);
-
return NULL;
}
void silc_server_update_clients_by_server(SilcServer server,
SilcServerEntry from,
SilcServerEntry to,
- bool resolve_real_server)
+ SilcBool resolve_real_server)
{
- SilcIDCacheList list = NULL;
+ SilcList list;
SilcIDCacheEntry id_cache = NULL;
SilcClientEntry client = NULL;
- bool local;
+ SilcBool local;
if (from && from->id) {
SILC_LOG_DEBUG(("Changing from server %s",
SILC_LOG_DEBUG(("global list"));
local = FALSE;
if (silc_idcache_get_all(server->global_list->clients, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- client = (SilcClientEntry)id_cache->context;
-
- /* If entry is disabled skip it. If entry is local to us, do not
- switch it to anyone else, it is ours so skip it. */
- if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
- SILC_IS_LOCAL(client)) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- else
- continue;
- }
-
- SILC_LOG_DEBUG(("Client %s",
- silc_id_render(client->id, SILC_ID_CLIENT)));
- if (client->router && client->router->id)
- SILC_LOG_DEBUG(("Client->router %s",
- silc_id_render(client->router->id, SILC_ID_SERVER)));
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ client = (SilcClientEntry)id_cache->context;
+
+ /* If entry is disabled skip it. If entry is local to us, do not
+ switch it to anyone else, it is ours so skip it. */
+ if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
+ SILC_IS_LOCAL(client))
+ continue;
- if (from) {
- if (client->router == from) {
- if (resolve_real_server) {
- client->router =
- silc_server_update_clients_by_real_server(server, from, to,
- client, local,
- id_cache);
- if (!client->router) {
- if (server->server_type == SILC_ROUTER)
- client->router = from;
- else
- client->router = to;
- }
- } else {
- client->router = to;
+ SILC_LOG_DEBUG(("Client %s",
+ silc_id_render(client->id, SILC_ID_CLIENT)));
+ if (client->router && client->router->id)
+ SILC_LOG_DEBUG(("Client->router %s",
+ silc_id_render(client->router->id, SILC_ID_SERVER)));
+
+ if (from) {
+ if (client->router == from) {
+ if (resolve_real_server) {
+ client->router =
+ silc_server_update_clients_by_real_server(server, from, to,
+ client, local,
+ id_cache);
+ if (!client->router) {
+ if (server->server_type == SILC_ROUTER)
+ client->router = from;
+ else
+ client->router = to;
}
+ } else {
+ client->router = to;
}
- } else {
- /* All are changed */
- if (resolve_real_server)
- /* Call this so that the entry is moved to correct list if
- needed. No resolving by real server is actually done. */
- silc_server_update_clients_by_real_server(server, NULL, to,
- client, local,
- id_cache);
-
- client->router = to;
}
-
- if (client->router && client->router->id)
- SILC_LOG_DEBUG(("Client changed to %s",
- silc_id_render(client->router->id, SILC_ID_SERVER)));
-
- if (!silc_idcache_list_next(list, &id_cache))
- break;
+ } else {
+ /* All are changed */
+ if (resolve_real_server)
+ /* Call this so that the entry is moved to correct list if
+ needed. No resolving by real server is actually done. */
+ silc_server_update_clients_by_real_server(server, NULL, to,
+ client, local,
+ id_cache);
+
+ client->router = to;
}
+
+ if (client->router && client->router->id)
+ SILC_LOG_DEBUG(("Client changed to %s",
+ silc_id_render(client->router->id, SILC_ID_SERVER)));
}
- silc_idcache_list_free(list);
}
SILC_LOG_DEBUG(("local list"));
local = TRUE;
if (silc_idcache_get_all(server->local_list->clients, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- client = (SilcClientEntry)id_cache->context;
-
- /* If entry is disabled skip it. If entry is local to us, do not
- switch it to anyone else, it is ours so skip it. */
- if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
- SILC_IS_LOCAL(client)) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- else
- continue;
- }
-
- SILC_LOG_DEBUG(("Client %s",
- silc_id_render(client->id, SILC_ID_CLIENT)));
- if (client->router && client->router->id)
- SILC_LOG_DEBUG(("Client->router %s",
- silc_id_render(client->router->id, SILC_ID_SERVER)));
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ client = (SilcClientEntry)id_cache->context;
+
+ /* If entry is disabled skip it. If entry is local to us, do not
+ switch it to anyone else, it is ours so skip it. */
+ if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
+ SILC_IS_LOCAL(client))
+ continue;
- if (from) {
- if (client->router == from) {
- if (resolve_real_server) {
- client->router =
- silc_server_update_clients_by_real_server(server, from, to,
- client, local,
- id_cache);
- if (!client->router)
- client->router = from;
- } else {
- client->router = to;
- }
+ SILC_LOG_DEBUG(("Client %s",
+ silc_id_render(client->id, SILC_ID_CLIENT)));
+ if (client->router && client->router->id)
+ SILC_LOG_DEBUG(("Client->router %s",
+ silc_id_render(client->router->id, SILC_ID_SERVER)));
+
+ if (from) {
+ if (client->router == from) {
+ if (resolve_real_server) {
+ client->router =
+ silc_server_update_clients_by_real_server(server, from, to,
+ client, local,
+ id_cache);
+ if (!client->router)
+ client->router = from;
+ } else {
+ client->router = to;
}
- } else {
- /* All are changed */
- if (resolve_real_server)
- /* Call this so that the entry is moved to correct list if
- needed. No resolving by real server is actually done. */
- silc_server_update_clients_by_real_server(server, NULL, to,
- client, local,
- id_cache);
-
- client->router = to;
}
-
- if (client->router && client->router->id)
- SILC_LOG_DEBUG(("Client changed to %s",
- silc_id_render(client->router->id, SILC_ID_SERVER)));
-
- if (!silc_idcache_list_next(list, &id_cache))
- break;
+ } else {
+ /* All are changed */
+ if (resolve_real_server)
+ /* Call this so that the entry is moved to correct list if
+ needed. No resolving by real server is actually done. */
+ silc_server_update_clients_by_real_server(server, NULL, to,
+ client, local,
+ id_cache);
+
+ client->router = to;
}
+
+ if (client->router && client->router->id)
+ SILC_LOG_DEBUG(("Client changed to %s",
+ silc_id_render(client->router->id, SILC_ID_SERVER)));
}
- silc_idcache_list_free(list);
}
}
SilcServerEntry from,
SilcServerEntry to)
{
- SilcIDCacheList list = NULL;
+ SilcList list;
SilcIDCacheEntry id_cache = NULL;
SilcServerEntry server_entry = NULL;
SILC_LOG_DEBUG(("Updating servers"));
if (silc_idcache_get_all(server->local_list->servers, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- server_entry = (SilcServerEntry)id_cache->context;
-
- /* If entry is local to us, do not switch it to any anyone else,
- it is ours. */
- if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
- server_entry == from) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- else
- continue;
- }
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ server_entry = (SilcServerEntry)id_cache->context;
- /* If we are standalone router, any server that is not directly
- connected to cannot exist anymore. If we are not standalone
- we update it correctly. */
- if (server->server_type == SILC_ROUTER && server->standalone) {
- silc_server_backup_del(server, server_entry);
- silc_server_backup_replaced_del(server, server_entry);
- silc_idlist_del_data(server_entry);
- silc_idlist_del_server(server->local_list, server_entry);
- server->stat.servers--;
- server->stat.cell_servers--;
- } else {
- /* XXX if we are not standalone, do a check from local config
- whether this server is in our cell, but not connected to
- us (in which case we must remove it). */
-
- if (from) {
- if (server_entry->router == from) {
- SILC_LOG_DEBUG(("Updating server (local) %s",
- server_entry->server_name ?
- server_entry->server_name : ""));
- server_entry->router = to;
- server_entry->connection = to->connection;
- }
- } else {
- /* Update all */
+ /* If entry is local to us, do not switch it to any anyone else,
+ it is ours. */
+ if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
+ server_entry == from)
+ continue;
+
+ /* If we are standalone router, any server that is not directly
+ connected to cannot exist anymore. If we are not standalone
+ we update it correctly. */
+ if (server->server_type == SILC_ROUTER && server->standalone) {
+ silc_server_backup_del(server, server_entry);
+ silc_server_backup_replaced_del(server, server_entry);
+ silc_idlist_del_data(server_entry);
+ silc_idlist_del_server(server->local_list, server_entry);
+ server->stat.servers--;
+ server->stat.cell_servers--;
+ } else {
+ /* XXX if we are not standalone, do a check from local config
+ whether this server is in our cell, but not connected to
+ us (in which case we must remove it). */
+
+ if (from) {
+ if (server_entry->router == from) {
SILC_LOG_DEBUG(("Updating server (local) %s",
server_entry->server_name ?
server_entry->server_name : ""));
server_entry->router = to;
server_entry->connection = to->connection;
}
+ } else {
+ /* Update all */
+ SILC_LOG_DEBUG(("Updating server (local) %s",
+ server_entry->server_name ?
+ server_entry->server_name : ""));
+ server_entry->router = to;
+ server_entry->connection = to->connection;
}
-
- if (!silc_idcache_list_next(list, &id_cache))
- break;
}
}
- silc_idcache_list_free(list);
}
if (silc_idcache_get_all(server->global_list->servers, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- server_entry = (SilcServerEntry)id_cache->context;
-
- /* If entry is local to us, do not switch it to anyone else,
- it is ours. */
- if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
- server_entry == from) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- else
- continue;
- }
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ server_entry = (SilcServerEntry)id_cache->context;
- /* If we are standalone router, any server that is not directly
- connected to cannot exist anymore. If we are not standalone
- we update it correctly. */
- if (server->server_type == SILC_ROUTER && server->standalone) {
- silc_server_backup_del(server, server_entry);
- silc_server_backup_replaced_del(server, server_entry);
- silc_idlist_del_data(server_entry);
- silc_idlist_del_server(server->global_list, server_entry);
- server->stat.servers--;
- server->stat.cell_servers--;
- } else {
- /* XXX if we are not standalone, do a check from local config
- whether this server is in our cell, but not connected to
- us (in which case we must remove it). */
-
- if (from) {
- if (server_entry->router == from) {
- SILC_LOG_DEBUG(("Updating server (global) %s",
- server_entry->server_name ?
- server_entry->server_name : ""));
- server_entry->router = to;
- server_entry->connection = to->connection;
- }
- } else {
- /* Update all */
+ /* If entry is local to us, do not switch it to anyone else,
+ it is ours. */
+ if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
+ server_entry == from)
+ continue;
+
+ /* If we are standalone router, any server that is not directly
+ connected to cannot exist anymore. If we are not standalone
+ we update it correctly. */
+ if (server->server_type == SILC_ROUTER && server->standalone) {
+ silc_server_backup_del(server, server_entry);
+ silc_server_backup_replaced_del(server, server_entry);
+ silc_idlist_del_data(server_entry);
+ silc_idlist_del_server(server->global_list, server_entry);
+ server->stat.servers--;
+ server->stat.cell_servers--;
+ } else {
+ /* XXX if we are not standalone, do a check from local config
+ whether this server is in our cell, but not connected to
+ us (in which case we must remove it). */
+
+ if (from) {
+ if (server_entry->router == from) {
SILC_LOG_DEBUG(("Updating server (global) %s",
server_entry->server_name ?
server_entry->server_name : ""));
server_entry->router = to;
server_entry->connection = to->connection;
}
+ } else {
+ /* Update all */
+ SILC_LOG_DEBUG(("Updating server (global) %s",
+ server_entry->server_name ?
+ server_entry->server_name : ""));
+ server_entry->router = to;
+ server_entry->connection = to->connection;
}
-
- if (!silc_idcache_list_next(list, &id_cache))
- break;
}
}
- silc_idcache_list_free(list);
}
}
dropped if `toggle_enabled' is FALSE, after this function is called. */
void silc_server_local_servers_toggle_enabled(SilcServer server,
- bool toggle_enabled)
+ SilcBool toggle_enabled)
{
- SilcIDCacheList list = NULL;
+ SilcList list;
SilcIDCacheEntry id_cache = NULL;
SilcServerEntry server_entry = NULL;
if (silc_idcache_get_all(server->local_list->servers, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- server_entry = (SilcServerEntry)id_cache->context;
- if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- else
- continue;
- }
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ server_entry = (SilcServerEntry)id_cache->context;
+ if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry)
+ continue;
- if (toggle_enabled)
- server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
- else
- server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
+ if (toggle_enabled)
+ server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+ else
+ server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- }
}
- silc_idcache_list_free(list);
}
if (silc_idcache_get_all(server->global_list->servers, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- server_entry = (SilcServerEntry)id_cache->context;
- if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- else
- continue;
- }
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ server_entry = (SilcServerEntry)id_cache->context;
+ if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry)
+ continue;
- if (toggle_enabled)
- server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
- else
- server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
+ if (toggle_enabled)
+ server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+ else
+ server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- }
}
- silc_idcache_list_free(list);
}
}
void silc_server_remove_servers_by_server(SilcServer server,
SilcServerEntry from,
- bool remove_clients)
+ SilcBool remove_clients)
{
- SilcIDCacheList list = NULL;
+ SilcList list;
SilcIDCacheEntry id_cache = NULL;
SilcServerEntry server_entry = NULL;
from->server_name ? from->server_name : "server"));
if (silc_idcache_get_all(server->local_list->servers, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- server_entry = (SilcServerEntry)id_cache->context;
- if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
- server_entry->router != from || server_entry == from) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- else
- continue;
- }
-
- /* Remove clients owned by this server */
- if (remove_clients)
- silc_server_remove_clients_by_server(server, from, server_entry,
- TRUE);
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ server_entry = (SilcServerEntry)id_cache->context;
+ if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
+ server_entry->router != from || server_entry == from)
+ continue;
- /* Remove the server */
- silc_server_backup_del(server, server_entry);
- silc_idlist_del_server(server->local_list, server_entry);
+ /* Remove clients owned by this server */
+ if (remove_clients)
+ silc_server_remove_clients_by_server(server, from, server_entry,
+ TRUE);
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- }
+ /* Remove the server */
+ silc_server_backup_del(server, server_entry);
+ silc_idlist_del_server(server->local_list, server_entry);
}
- silc_idcache_list_free(list);
}
if (silc_idcache_get_all(server->global_list->servers, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- server_entry = (SilcServerEntry)id_cache->context;
- if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
- server_entry->router != from || server_entry == from) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- else
- continue;
- }
-
- /* Remove clients owned by this server */
- if (remove_clients)
- silc_server_remove_clients_by_server(server, from, server_entry,
- TRUE);
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ server_entry = (SilcServerEntry)id_cache->context;
+ if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
+ server_entry->router != from || server_entry == from)
+ continue;
- /* Remove the server */
- silc_server_backup_del(server, server_entry);
- silc_idlist_del_server(server->global_list, server_entry);
+ /* Remove clients owned by this server */
+ if (remove_clients)
+ silc_server_remove_clients_by_server(server, from, server_entry,
+ TRUE);
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- }
+ /* Remove the server */
+ silc_server_backup_del(server, server_entry);
+ silc_idlist_del_server(server->global_list, server_entry);
}
- silc_idcache_list_free(list);
}
}
void silc_server_remove_channels_by_server(SilcServer server,
SilcServerEntry from)
{
- SilcIDCacheList list = NULL;
+ SilcList list;
SilcIDCacheEntry id_cache = NULL;
SilcChannelEntry channel = NULL;
SILC_LOG_DEBUG(("Removing channels by server"));
if (silc_idcache_get_all(server->global_list->channels, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- channel = (SilcChannelEntry)id_cache->context;
- if (channel->router == from)
- silc_idlist_del_channel(server->global_list, channel);
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- }
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ channel = (SilcChannelEntry)id_cache->context;
+ if (channel->router == from)
+ silc_idlist_del_channel(server->global_list, channel);
}
- silc_idcache_list_free(list);
}
}
SilcServerEntry from,
SilcServerEntry to)
{
- SilcIDCacheList list = NULL;
+ SilcList list;
SilcIDCacheEntry id_cache = NULL;
SilcChannelEntry channel = NULL;
SILC_LOG_DEBUG(("Updating channels by server"));
if (silc_idcache_get_all(server->global_list->channels, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- channel = (SilcChannelEntry)id_cache->context;
- if (from) {
- if (channel->router == from)
- channel->router = to;
- } else {
- /* Update all */
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ channel = (SilcChannelEntry)id_cache->context;
+ if (from) {
+ if (channel->router == from)
channel->router = to;
- }
- if (!silc_idcache_list_next(list, &id_cache))
- break;
+ } else {
+ /* Update all */
+ channel->router = to;
}
}
- silc_idcache_list_free(list);
}
}
/* Checks whether given channel has global users. If it does this returns
TRUE and FALSE if there is only locally connected clients on the channel. */
-bool silc_server_channel_has_global(SilcChannelEntry channel)
+SilcBool silc_server_channel_has_global(SilcChannelEntry channel)
{
SilcChannelClientEntry chl;
SilcHashTableList htl;
/* Checks whether given channel has locally connected users. If it does this
returns TRUE and FALSE if there is not one locally connected client. */
-bool silc_server_channel_has_local(SilcChannelEntry channel)
+SilcBool silc_server_channel_has_local(SilcChannelEntry channel)
{
SilcChannelClientEntry chl;
SilcHashTableList htl;
users are removed from the channel. Returns TRUE if the channel is
destroyed totally, and FALSE if it is permanent and remains. */
-bool silc_server_channel_delete(SilcServer server,
- SilcChannelEntry channel)
+SilcBool silc_server_channel_delete(SilcServer server,
+ SilcChannelEntry channel)
{
SilcChannelClientEntry chl;
SilcHashTableList htl;
- bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
+ SilcBool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
SILC_LOG_DEBUG(("Deleting channel %s", channel->channel_name));
always in up to date thus we can only check the channel list from
`client' which is faster than checking the user list from `channel'. */
-bool silc_server_client_on_channel(SilcClientEntry client,
- SilcChannelEntry channel,
- SilcChannelClientEntry *chl)
+SilcBool silc_server_client_on_channel(SilcClientEntry client,
+ SilcChannelEntry channel,
+ SilcChannelClientEntry *chl)
{
if (!client || !channel)
return FALSE;
}
/* Find number of sockets by IP address indicated by `ip'. Returns 0 if
- socket connections with the IP address does not exist. */
+ socket connections with the IP address does not exist. Counts only
+ fully established connections. */
SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
- SilcSocketType type)
+ SilcConnectionType type)
{
- int i, count;
-
- for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
- if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
- !SILC_IS_HOST_LOOKUP(server->sockets[i]) &&
- !strcmp(server->sockets[i]->ip, ip) &&
- server->sockets[i]->type == type)
+ SilcServerConnection conn;
+ SilcIDListData idata;
+ const char *ipaddr;
+ int count = 0;
+
+ silc_dlist_start(server->conns);
+ while ((conn = silc_dlist_get(server->conns))) {
+ if (!conn->sock)
+ continue;
+ silc_socket_stream_get_info(conn->sock, NULL, NULL, &ipaddr, NULL);
+ idata = silc_packet_get_context(conn->sock);
+ if (!strcmp(ipaddr, ip) && idata && idata->conn_type == type)
count++;
}
return count;
}
+/* Find active socket connection by the IP address and port indicated by
+ `ip' and `port', and socket connection type of `type'. */
+
+SilcPacketStream
+silc_server_find_socket_by_host(SilcServer server,
+ SilcConnectionType type,
+ const char *ip, SilcUInt16 port)
+{
+ SilcServerConnection conn;
+ SilcIDListData idata;
+ const char *ipaddr;
+
+ silc_dlist_start(server->conns);
+ while ((conn = silc_dlist_get(server->conns))) {
+ if (!conn->sock)
+ continue;
+ idata = silc_packet_get_context(conn->sock);
+ silc_socket_stream_get_info(conn->sock, NULL, NULL, &ipaddr, NULL);
+ if (!strcmp(ipaddr, ip) &&
+ (!port || conn->remote_port == port) &&
+ idata->conn_type == type)
+ return conn->sock;
+ }
+
+ return NULL;
+}
+
/* Find number of sockets by IP address indicated by remote host, indicatd
by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
does not exist. If `ip' is provided then `hostname' is ignored. */
SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
const char *ip,
const char *hostname,
- SilcUInt16 port,
- SilcSocketType type)
+ SilcUInt16 port)
{
- int i, count;
+ SilcServerConnection conn;
+ int count = 0;
if (!ip && !hostname)
return 0;
- for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
- if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
- !SILC_IS_HOST_LOOKUP(server->sockets[i]) &&
- ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
- (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
- server->sockets[i]->port == port &&
- server->sockets[i]->type == type)
+ silc_dlist_start(server->conns);
+ while ((conn = silc_dlist_get(server->conns))) {
+ if (((ip && !strcmp(conn->remote_host, ip)) ||
+ (hostname && !strcmp(conn->remote_host, hostname))) &&
+ conn->remote_port == port)
count++;
}
return count;
}
-/* Finds locally cached public key by the public key received in the SKE.
- If we have it locally cached then we trust it and will use it in the
- authentication protocol. Returns the locally cached public key or NULL
- if we do not find the public key. */
+/* SKR find callbcak */
-SilcPublicKey silc_server_find_public_key(SilcServer server,
- SilcHashTable local_public_keys,
- SilcPublicKey remote_public_key)
+static void find_callback(SilcSKR skr, SilcSKRFind find,
+ SilcSKRStatus status, SilcDList keys,
+ void *context)
{
- SilcPublicKey cached_key;
-
- SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
- silc_hash_table_count(local_public_keys)));
-
- if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
- (void *)&cached_key, NULL,
- silc_hash_public_key, NULL,
- silc_hash_public_key_compare, NULL)) {
- SILC_LOG_ERROR(("Public key not found"));
- return NULL;
+ SilcPublicKey *public_key = context;
+ SilcSKRKey key;
+
+ if (keys) {
+ silc_dlist_start(keys);
+ key = silc_dlist_get(keys);
+ *public_key = key->key;
+ silc_dlist_uninit(keys);
}
- SILC_LOG_DEBUG(("Found public key"));
-
- return cached_key;
+ silc_skr_find_free(find);
}
-/* This returns the first public key from the table of public keys. This
- is used only in cases where single public key exists in the table and
- we want to get a pointer to it. For public key tables that has multiple
- keys in it the silc_server_find_public_key must be used. */
+/* Get public key. For public key tables that has multiple keys in it the
+ silc_server_find_public_key must be used. */
SilcPublicKey silc_server_get_public_key(SilcServer server,
- SilcHashTable local_public_keys)
+ SilcSKRKeyUsage usage,
+ void *key_context)
{
- SilcPublicKey cached_key;
- SilcHashTableList htl;
+ SilcSKRFind find;
+ SilcPublicKey public_key = NULL;
SILC_LOG_DEBUG(("Start"));
- assert(silc_hash_table_count(local_public_keys) < 2);
-
- silc_hash_table_list(local_public_keys, &htl);
- if (!silc_hash_table_get(&htl, NULL, (void *)&cached_key)) {
- silc_hash_table_list_reset(&htl);
+ find = silc_skr_find_alloc();
+ if (!find)
return NULL;
- }
- silc_hash_table_list_reset(&htl);
- return cached_key;
+ silc_skr_find_set_usage(find, usage);
+ silc_skr_find_set_context(find, key_context);
+ silc_skr_find(server->repository, server->schedule,
+ find, find_callback, &public_key);
+
+ return public_key;
}
/* Check whether the connection `sock' is allowed to connect to us. This
checks for example whether there is too much connections for this host,
and required version for the host etc. */
-bool silc_server_connection_allowed(SilcServer server,
- SilcSocketConnection sock,
- SilcSocketType type,
- SilcServerConfigConnParams *global,
- SilcServerConfigConnParams *params,
- SilcSKE ske)
+SilcBool silc_server_connection_allowed(SilcServer server,
+ SilcPacketStream sock,
+ SilcConnectionType type,
+ SilcServerConfigConnParams *global,
+ SilcServerConfigConnParams *params,
+ SilcSKE ske)
{
- SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
+ SilcUInt32 conn_number = (type == SILC_CONN_CLIENT ?
server->stat.my_clients :
- type == SILC_SOCKET_TYPE_SERVER ?
+ type == SILC_CONN_SERVER ?
server->stat.my_servers :
server->stat.my_routers);
SilcUInt32 num_sockets, max_hosts, max_per_host;
SilcUInt32 r_protocol_version, l_protocol_version;
SilcUInt32 r_software_version, l_software_version;
char *r_vendor_version = NULL, *l_vendor_version;
+ const char *hostname, *ip;
+
+ silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
SILC_LOG_DEBUG(("Checking whether connection is allowed"));
if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
&r_software_version, NULL,
&r_vendor_version)) {
- sock->version = r_protocol_version;
-
/* Match protocol version */
if (l_protocol_version && r_protocol_version &&
r_protocol_version < l_protocol_version) {
SILC_LOG_INFO(("Connection %s (%s) is too old version",
- sock->hostname, sock->ip));
- sock->protocol = NULL;
+ hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_BAD_VERSION,
"You support too old protocol version");
if (l_software_version && r_software_version &&
r_software_version < l_software_version) {
SILC_LOG_INFO(("Connection %s (%s) is too old version",
- sock->hostname, sock->ip));
- sock->protocol = NULL;
+ hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_BAD_VERSION,
"You support too old software version");
if (l_vendor_version && r_vendor_version &&
!silc_string_match(l_vendor_version, r_vendor_version)) {
SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
- sock->hostname, sock->ip));
- sock->protocol = NULL;
+ hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_BAD_VERSION,
"Your software is not supported");
/* Check for maximum connections limit */
- num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
+ num_sockets = silc_server_num_sockets_by_ip(server, ip, type);
max_hosts = (params ? params->connections_max : global->connections_max);
max_per_host = (params ? params->connections_max_per_host :
global->connections_max_per_host);
if (max_hosts && conn_number >= max_hosts) {
SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
- sock->hostname, sock->ip));
- sock->protocol = NULL;
+ hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_RESOURCE_LIMIT,
"Server is full, try again later");
if (num_sockets >= max_per_host) {
SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
- sock->hostname, sock->ip));
- sock->protocol = NULL;
+ hostname, ip));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_RESOURCE_LIMIT,
"Too many connections from your host");
/* Checks that client has rights to add or remove channel modes. If any
of the checks fails FALSE is returned. */
-bool silc_server_check_cmode_rights(SilcServer server,
+SilcBool silc_server_check_cmode_rights(SilcServer server,
SilcChannelEntry channel,
SilcChannelClientEntry client,
SilcUInt32 mode)
{
- bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
- bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
+ SilcBool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
+ SilcBool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
/* Check whether has rights to change anything */
if (!is_op && !is_fo)
/* Check that the client has rights to change its user mode. Returns
FALSE if setting some mode is not allowed. */
-bool silc_server_check_umode_rights(SilcServer server,
+SilcBool silc_server_check_umode_rights(SilcServer server,
SilcClientEntry client,
SilcUInt32 mode)
{
- bool server_op = FALSE, router_op = FALSE;
+ SilcBool server_op = FALSE, router_op = FALSE;
if (mode & SILC_UMODE_SERVER_OPERATOR) {
/* Cannot set server operator mode (must use OPER command) */
incoming client connection. */
void silc_server_send_connect_notifys(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcClientEntry client)
{
- SilcIDListData idata = (SilcIDListData)client;
+ SilcCipher key;
SILC_LOG_DEBUG(("Send welcome notifys"));
server->stat.my_router_ops +
server->stat.my_server_ops));
+ silc_packet_get_keys(sock, &key, NULL, NULL, NULL);
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
("Your connection is secured with %s cipher, "
"key length %d bits",
- silc_cipher_get_name(idata->send_key),
- silc_cipher_get_key_len(idata->send_key)));
+ silc_cipher_get_name(key),
+ silc_cipher_get_key_len(key)));
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
("Your current nickname is %s",
client->nickname));
to the channel. */
silc_server_send_notify_on_channels(server, remote_client,
remote_client, SILC_NOTIFY_TYPE_KILLED,
- 3, killed->data, killed->len,
+ 3, killed->data, silc_buffer_len(killed),
comment, comment ? strlen(comment) : 0,
- killer->data, killer->len);
+ killer->data, silc_buffer_len(killer));
/* Send KILLED notify to primary route */
silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
disconnect the client here */
if (remote_client->connection) {
/* Remove locally conneted client */
- SilcSocketConnection sock = remote_client->connection;
+ SilcPacketStream sock = remote_client->connection;
silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
silc_server_close_connection(server, sock);
} else {
{
WatcherNotifyContext *notify = user_context;
SilcClientEntry entry = context;
- SilcSocketConnection sock;
+ SilcPacketStream sock;
if (!context)
return;
public key is being watched by someone, and notifies the watcher of the
notify change of notify type indicated by `notify'. */
-bool silc_server_check_watcher_list(SilcServer server,
+SilcBool silc_server_check_watcher_list(SilcServer server,
SilcClientEntry client,
const char *new_nick,
SilcNotifyType notify)
/* Remove the `client' from watcher list. After calling this the `client'
is not watching any nicknames. */
-bool silc_server_del_from_watcher_list(SilcServer server,
+SilcBool silc_server_del_from_watcher_list(SilcServer server,
SilcClientEntry client)
{
SilcHashTableList htl;
void *key;
SilcClientEntry entry;
- bool found = FALSE;
+ SilcBool found = FALSE;
silc_hash_table_list(server->watcher_list, &htl);
while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
/* Force the client indicated by `chl' to change the channel user mode
on channel indicated by `channel' to `forced_mode'. */
-bool silc_server_force_cumode_change(SilcServer server,
- SilcSocketConnection sock,
- SilcChannelEntry channel,
- SilcChannelClientEntry chl,
- SilcUInt32 forced_mode)
+SilcBool silc_server_force_cumode_change(SilcServer server,
+ SilcPacketStream sock,
+ SilcChannelEntry channel,
+ SilcChannelClientEntry chl,
+ SilcUInt32 forced_mode)
{
SilcBuffer idp1, idp2;
unsigned char cumode[4];
SILC_PUT32_MSB(forced_mode, cumode);
silc_server_send_notify_to_channel(server, sock, channel, FALSE, TRUE,
SILC_NOTIFY_TYPE_CUMODE_CHANGE,
- 3, idp1->data, idp1->len,
+ 3, idp1->data, silc_buffer_len(idp1),
cumode, sizeof(cumode),
- idp2->data, idp2->len);
+ idp2->data, silc_buffer_len(idp2));
silc_buffer_free(idp1);
silc_buffer_free(idp2);
return TRUE;
}
-/* Find active socket connection by the IP address and port indicated by
- `ip' and `port', and socket connection type of `type'. */
-
-SilcSocketConnection
-silc_server_find_socket_by_host(SilcServer server,
- SilcSocketType type,
- const char *ip, SilcUInt16 port)
-{
- int i;
-
- for (i = 0; i < server->config->param.connections_max; i++) {
- if (!server->sockets[i] || SILC_IS_HOST_LOOKUP(server->sockets[i]))
- continue;
- if (!strcmp(server->sockets[i]->ip, ip) &&
- (!port || server->sockets[i]->port == port) &&
- server->sockets[i]->type == type)
- return server->sockets[i];
- }
-
- return NULL;
-}
-
/* This function can be used to match the invite and ban lists. */
-bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
- SilcUInt8 type, void *check)
+SilcBool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
+ SilcUInt8 type, void *check)
{
unsigned char *tmp = NULL;
SilcUInt32 len = 0, t;
SilcHashTableList htl;
SilcBuffer entry, idp = NULL, pkp = NULL;
- bool ret = FALSE;
+ SilcBool ret = FALSE;
SILC_LOG_DEBUG(("Matching invite/ban"));
return FALSE;
}
if (type == 2) {
- pkp = silc_pkcs_public_key_payload_encode(check);
+ pkp = silc_public_key_payload_encode(check);
if (!pkp)
return FALSE;
tmp = pkp->data;
- len = pkp->len;
+ len = silc_buffer_len(pkp);
}
if (type == 3) {
idp = silc_id_payload_encode(check, SILC_ID_CLIENT);
if (!idp)
return FALSE;
tmp = idp->data;
- len = idp->len;
+ len = silc_buffer_len(idp);
}
/* Compare the list */
/* Process invite or ban information */
-bool silc_server_inviteban_process(SilcServer server, SilcHashTable list,
+SilcBool silc_server_inviteban_process(SilcServer server, SilcHashTable list,
SilcUInt8 action, SilcArgumentPayload args)
{
unsigned char *tmp;
SilcPublicKey pk;
/* Verify validity of the public key */
- if (!silc_pkcs_public_key_payload_decode(tmp, len, &pk)) {
+ if (!silc_public_key_payload_decode(tmp, len, &pk)) {
tmp = silc_argument_get_next_arg(args, &type, &len);
continue;
}
SilcPublicKey pk;
/* Verify validity of the public key */
- if (!silc_pkcs_public_key_payload_decode(tmp, len, &pk)) {
+ if (!silc_public_key_payload_decode(tmp, len, &pk)) {
tmp = silc_argument_get_next_arg(args, &type, &len);
continue;
}
{
silc_schedule_task_del_by_callback(server->schedule,
silc_server_connect_to_router);
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router, server, 0, 1,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_connect_to_router, server, 0, 1);
}
static void
return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
/* Decode the public key */
- if (!silc_pkcs_public_key_payload_decode((unsigned char *)pk, pk_len, &chpk))
+ if (!silc_public_key_payload_decode((unsigned char *)pk, pk_len, &chpk))
return SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY;
/* Create channel public key list (hash table) if needed */
if (type == 0x00) {
/* Add new public key to channel public key list */
- SILC_LOG_DEBUG(("Add new channel public key %s to channel %s",
- chpk->identifier, channel->channel_name));
+ SILC_LOG_DEBUG(("Add new channel public key to channel %s",
+ channel->channel_name));
/* Check for resource limit */
if (silc_hash_table_count(channel->channel_pubkeys) > 64) {
SilcBuffer silc_server_get_channel_pk_list(SilcServer server,
SilcChannelEntry channel,
- bool announce,
- bool delete)
+ SilcBool announce,
+ SilcBool delete)
{
SilcHashTableList htl;
SilcBuffer list, pkp;
silc_hash_table_list(channel->channel_pubkeys, &htl);
while (silc_hash_table_get(&htl, NULL, (void *)&pk)) {
- pkp = silc_pkcs_public_key_payload_encode(pk);
- list = silc_argument_payload_encode_one(list, pkp->data, pkp->len,
+ pkp = silc_public_key_payload_encode(pk);
+ list = silc_argument_payload_encode_one(list, pkp->data,
+ silc_buffer_len(pkp),
announce ? 0x03 :
delete ? 0x01 : 0x00);
silc_buffer_free(pkp);
/* Sets the channel public keys into channel from the list of public keys. */
SilcStatus silc_server_set_channel_pk_list(SilcServer server,
- SilcSocketConnection sender,
+ SilcPacketStream sender,
SilcChannelEntry channel,
const unsigned char *pklist,
SilcUInt32 pklist_len)
SILC_PUT32_MSB(channel->user_limit, ulimit);
silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
- sidp->data, sidp->len,
+ sidp->data, silc_buffer_len(sidp),
mask, 4,
channel->cipher,
channel->cipher ?
/* Verifies the Authentication Payload `auth' with one of the public keys
on the `channel' public key list. */
-bool silc_server_verify_channel_auth(SilcServer server,
+SilcBool silc_server_verify_channel_auth(SilcServer server,
SilcChannelEntry channel,
SilcClientID *client_id,
const unsigned char *auth,
SilcPublicKey chpk;
unsigned char *pkhash;
SilcUInt32 pkhash_len;
- bool ret = FALSE;
+ SilcBool ret = FALSE;
SILC_LOG_DEBUG(("Verifying channel authentication"));
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2005, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
`router' and are owned by `entry'. `router' and `entry' can be same
too. If `server_signoff' is TRUE then SERVER_SIGNOFF notify is
distributed to our local clients. */
-bool silc_server_remove_clients_by_server(SilcServer server,
+SilcBool silc_server_remove_clients_by_server(SilcServer server,
SilcServerEntry router,
SilcServerEntry entry,
- bool server_signoff);
+ SilcBool server_signoff);
/* Updates the clients that are originated from the `from' to be originated
from the `to'. If the `resolve_real_server' is TRUE then this will
void silc_server_update_clients_by_server(SilcServer server,
SilcServerEntry from,
SilcServerEntry to,
- bool resolve_real_server);
+ SilcBool resolve_real_server);
/* Updates servers that are from `from' to be originated from `to'. This
will also update the server's connection to `to's connection. */
can be sent to the servers when `toggle_enabled' is TRUE and will be
dropped if `toggle_enabled' is FALSE, after this function is called. */
void silc_server_local_servers_toggle_enabled(SilcServer server,
- bool toggle_enabled);
+ SilcBool toggle_enabled);
/* Removes servers that are originated from the `from'. The server
entry is deleted in this function. If `remove_clients' is TRUE then
also does not remove locally connected servers. */
void silc_server_remove_servers_by_server(SilcServer server,
SilcServerEntry from,
- bool remove_clients);
+ SilcBool remove_clients);
/* Removes channels that are from `from. */
void silc_server_remove_channels_by_server(SilcServer server,
/* Checks whether given channel has global users. If it does this returns
TRUE and FALSE if there is only locally connected clients on the channel. */
-bool silc_server_channel_has_global(SilcChannelEntry channel);
+SilcBool silc_server_channel_has_global(SilcChannelEntry channel);
/* Checks whether given channel has locally connected users. If it does this
returns TRUE and FALSE if there is not one locally connected client. */
-bool silc_server_channel_has_local(SilcChannelEntry channel);
+SilcBool silc_server_channel_has_local(SilcChannelEntry channel);
/* This function removes the channel and all users on the channel, unless
the channel is permanent. In this case the channel is disabled but all
users are removed from the channel. Returns TRUE if the channel is
destroyed totally, and FALSE if it is permanent and remains. */
-bool silc_server_channel_delete(SilcServer server,
+SilcBool silc_server_channel_delete(SilcServer server,
SilcChannelEntry channel);
/* Returns TRUE if the given client is on the channel. FALSE if not.
This works because we assure that the user list on the channel is
always in up to date thus we can only check the channel list from
`client' which is faster than checking the user list from `channel'. */
-bool silc_server_client_on_channel(SilcClientEntry client,
+SilcBool silc_server_client_on_channel(SilcClientEntry client,
SilcChannelEntry channel,
SilcChannelClientEntry *chl);
/* Find number of sockets by IP address indicated by `ip'. Returns 0 if
socket connections with the IP address does not exist. */
SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
- SilcSocketType type);
+ SilcConnectionType type);
/* Find number of sockets by IP address indicated by remote host, indicated
by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
const char *ip,
const char *hostname,
- SilcUInt16 port,
- SilcSocketType type);
-
-/* Finds locally cached public key by the public key received in the SKE.
- If we have it locally cached then we trust it and will use it in the
- authentication protocol. Returns the locally cached public key or NULL
- if we do not find the public key. */
-SilcPublicKey silc_server_find_public_key(SilcServer server,
- SilcHashTable local_public_keys,
- SilcPublicKey remote_public_key);
-
-/* This returns the first public key from the table of public keys. This
- is used only in cases where single public key exists in the table and
- we want to get a pointer to it. For public key tables that has multiple
- keys in it the silc_server_find_public_key must be used. */
+ SilcUInt16 port);
+
+/* Get public key by key usage and key context. */
SilcPublicKey silc_server_get_public_key(SilcServer server,
- SilcHashTable local_public_keys);
+ SilcSKRKeyUsage usage,
+ void *key_context);
/* Check whether the connection `sock' is allowed to connect to us. This
checks for example whether there is too much connections for this host,
and required version for the host etc. */
-bool silc_server_connection_allowed(SilcServer server,
- SilcSocketConnection sock,
- SilcSocketType type,
- SilcServerConfigConnParams *global,
- SilcServerConfigConnParams *params,
- SilcSKE ske);
+SilcBool silc_server_connection_allowed(SilcServer server,
+ SilcPacketStream sock,
+ SilcConnectionType type,
+ SilcServerConfigConnParams *global,
+ SilcServerConfigConnParams *params,
+ SilcSKE ske);
/* Checks that client has rights to add or remove channel modes. If any
of the checks fails FALSE is returned. */
-bool silc_server_check_cmode_rights(SilcServer server,
+SilcBool silc_server_check_cmode_rights(SilcServer server,
SilcChannelEntry channel,
SilcChannelClientEntry client,
SilcUInt32 mode);
/* Check that the client has rights to change its user mode. Returns
FALSE if setting some mode is not allowed. */
-bool silc_server_check_umode_rights(SilcServer server,
+SilcBool silc_server_check_umode_rights(SilcServer server,
SilcClientEntry client,
SilcUInt32 mode);
/* This function is used to send the notify packets and motd to the
incoming client connection. */
void silc_server_send_connect_notifys(SilcServer server,
- SilcSocketConnection sock,
+ SilcPacketStream sock,
SilcClientEntry client);
/* Kill the client indicated by `remote_client' sending KILLED notify
/* This function checks whether the `client' nickname is being watched
by someone, and notifies the watcher of the notify change of notify
type indicated by `notify'. */
-bool silc_server_check_watcher_list(SilcServer server,
+SilcBool silc_server_check_watcher_list(SilcServer server,
SilcClientEntry client,
const char *new_nick,
SilcNotifyType notify);
/* Remove the `client' from watcher list. After calling this the `client'
is not watching any nicknames. */
-bool silc_server_del_from_watcher_list(SilcServer server,
+SilcBool silc_server_del_from_watcher_list(SilcServer server,
SilcClientEntry client);
/* Force the client indicated by `chl' to change the channel user mode
on channel indicated by `channel' to `forced_mode'. */
-bool silc_server_force_cumode_change(SilcServer server,
- SilcSocketConnection sock,
+SilcBool silc_server_force_cumode_change(SilcServer server,
+ SilcPacketStream sock,
SilcChannelEntry channel,
SilcChannelClientEntry chl,
SilcUInt32 forced_mode);
/* Find active socket connection by the IP address and port indicated by
`ip' and `port', and socket connection type of `type'. */
-SilcSocketConnection
+SilcPacketStream
silc_server_find_socket_by_host(SilcServer server,
- SilcSocketType type,
+ SilcConnectionType type,
const char *ip, SilcUInt16 port);
/* This function can be used to match the invite and ban lists. */
-bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
+SilcBool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
SilcUInt8 type, void *check);
/* Process invite or ban information */
-bool silc_server_inviteban_process(SilcServer server, SilcHashTable list,
+SilcBool silc_server_inviteban_process(SilcServer server, SilcHashTable list,
SilcUInt8 action, SilcArgumentPayload args);
/* Destructor for invite or ban list entrys */
/* Returns the channel public keys as Argument List payload. */
SilcBuffer silc_server_get_channel_pk_list(SilcServer server,
SilcChannelEntry channel,
- bool announce,
- bool delete);
+ SilcBool announce,
+ SilcBool delete);
/* Sets the channel public keys into channel from the list of public keys. */
SilcStatus silc_server_set_channel_pk_list(SilcServer server,
- SilcSocketConnection sender,
+ SilcPacketStream sender,
SilcChannelEntry channel,
const unsigned char *pklist,
SilcUInt32 pklist_len);
/* Verifies the Authentication Payload `auth' with one of the public keys
on the `channel' public key list. */
-bool silc_server_verify_channel_auth(SilcServer server,
+SilcBool silc_server_verify_channel_auth(SilcServer server,
SilcChannelEntry channel,
SilcClientID *client_id,
const unsigned char *auth,
Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Free the authentication fields in the specified struct
* Expands to two instructions */
#define CONFIG_FREE_AUTH(__section__) \
- silc_free(__section__->passphrase); \
- if (__section__->publickeys) \
- silc_hash_table_free(__section__->publickeys);
-
-static void my_free_public_key(void *key, void *context, void *user_data)
-{
- silc_pkcs_public_key_free(context);
-}
+ silc_free(__section__->passphrase);
/* Set default values to those parameters that have not been defined */
static void
return NULL;
}
+/* SKR find callbcak */
+
+static void my_find_callback(SilcSKR skr, SilcSKRFind find,
+ SilcSKRStatus status, SilcDList keys,
+ void *context)
+{
+ SilcSKRStatus *s = context;
+
+ *s = status;
+ if (keys)
+ silc_dlist_uninit(keys);
+
+ silc_skr_find_free(find);
+}
+
/* parse an authdata according to its auth method */
-static bool my_parse_authdata(SilcAuthMethod auth_meth, const char *p,
- void **auth_data, SilcUInt32 *auth_data_len)
+static SilcBool my_parse_authdata(SilcAuthMethod auth_meth, const char *p,
+ void **auth_data, SilcUInt32 *auth_data_len,
+ SilcSKRKeyUsage usage, void *key_context)
{
if (auth_meth == SILC_AUTH_PASSWORD) {
/* p is a plain text password */
} else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
/* p is a public key file name */
SilcPublicKey public_key;
- SilcPublicKey cached_key;
+ SilcSKR skr = *auth_data;
+ SilcSKRFind find;
+ SilcSKRStatus status;
- if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
- if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
- SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
- "Could not load public key file!"));
- return FALSE;
- }
+ if (!silc_pkcs_load_public_key(p, &public_key)) {
+ SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
+ "Could not load public key file!"));
+ return FALSE;
+ }
- if (*auth_data &&
- silc_hash_table_find_ext(*auth_data, public_key, (void *)&cached_key,
- NULL, silc_hash_public_key, NULL,
- silc_hash_public_key_compare, NULL)) {
+ find = silc_skr_find_alloc();
+ silc_skr_find_set_public_key(find, public_key);
+ silc_skr_find_set_usage(find, usage);
+ silc_skr_find_set_context(find, key_context ? key_context : (void *)usage);
+ silc_skr_find(skr, NULL, find, my_find_callback, &status);
+ if (status != SILC_SKR_OK) {
silc_pkcs_public_key_free(public_key);
SILC_SERVER_LOG_WARNING(("Warning: public key file \"%s\" already "
"configured, ignoring this key", p));
return TRUE; /* non fatal error */
}
- /* The auth_data is a pointer to the hash table of public keys. */
- if (auth_data) {
- if (*auth_data == NULL)
- *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
- NULL, NULL,
- my_free_public_key, NULL,
- TRUE);
- SILC_LOG_DEBUG(("Adding public key '%s' to authentication cache",
- public_key->identifier));
- silc_hash_table_add(*auth_data, public_key, public_key);
+ /* Add the public key to repository */
+ if (silc_skr_add_public_key(skr, public_key, usage,
+ key_context ? key_context : (void *)usage) !=
+ SILC_SKR_OK) {
+ SILC_SERVER_LOG_ERROR(("Error while adding public key \"%s\"", p));
+ return FALSE;
}
- } else
- abort();
+ }
return TRUE;
}
-static bool my_parse_publickeydir(const char *dirname, void **auth_data)
+static SilcBool my_parse_publickeydir(const char *dirname, void **auth_data,
+ SilcSKRKeyUsage usage)
{
int total = 0;
struct dirent *get_file;
SILC_SERVER_LOG_ERROR(("Error stating file %s: %s", buf,
strerror(errno)));
} else if (S_ISREG(check_file.st_mode)) {
- my_parse_authdata(SILC_AUTH_PUBLIC_KEY, buf, auth_data, NULL);
+ my_parse_authdata(SILC_AUTH_PUBLIC_KEY, buf, auth_data, NULL,
+ usage, NULL);
total++;
}
}
config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
}
else if (!strcmp(name, "prefer_passphrase_auth")) {
- config->prefer_passphrase_auth = *(bool *)val;
+ config->prefer_passphrase_auth = *(SilcBool *)val;
}
else if (!strcmp(name, "require_reverse_lookup")) {
- config->require_reverse_lookup = *(bool *)val;
+ config->require_reverse_lookup = *(SilcBool *)val;
}
else if (!strcmp(name, "connections_max")) {
config->param.connections_max = (SilcUInt32) *(int *)val;
config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
}
else if (!strcmp(name, "reconnect_keep_trying")) {
- config->param.reconnect_keep_trying = *(bool *)val;
+ config->param.reconnect_keep_trying = *(SilcBool *)val;
}
else if (!strcmp(name, "key_exchange_rekey")) {
config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
}
else if (!strcmp(name, "key_exchange_pfs")) {
- config->param.key_exchange_pfs = *(bool *)val;
+ config->param.key_exchange_pfs = *(SilcBool *)val;
}
else if (!strcmp(name, "channel_rekey_secs")) {
config->channel_rekey_secs = (SilcUInt32) *(int *)val;
(*(char *)val ? strdup((char *) val) : NULL);
}
else if (!strcmp(name, "detach_disabled")) {
- config->detach_disabled = *(bool *)val;
+ config->detach_disabled = *(SilcBool *)val;
}
else if (!strcmp(name, "detach_timeout")) {
config->detach_timeout = (SilcUInt32) *(int *)val;
}
else if (!strcmp(name, "qos")) {
- config->param.qos = *(bool *)val;
+ config->param.qos = *(SilcBool *)val;
}
else if (!strcmp(name, "qos_rate_limit")) {
config->param.qos_rate_limit = *(SilcUInt32 *)val;
CONFIG_IS_DOUBLE(server_info->public_key);
/* Try to load specified file, if fail stop config parsing */
- if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
- SILC_PKCS_FILE_PEM))
- if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
- SILC_PKCS_FILE_BIN)) {
- SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
- return SILC_CONFIG_EPRINTLINE;
- }
+ if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key)) {
+ SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
+ return SILC_CONFIG_EPRINTLINE;
+ }
}
else if (!strcmp(name, "privatekey")) {
struct stat st;
}
/* Try to load specified file, if fail stop config parsing */
- if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
- "", 0, SILC_PKCS_FILE_BIN))
- if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
- "", 0, SILC_PKCS_FILE_PEM)) {
- SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
- return SILC_CONFIG_EPRINTLINE;
- }
+ if (!silc_pkcs_load_private_key(file_tmp, "", 0,
+ &server_info->private_key)) {
+ SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
+ return SILC_CONFIG_EPRINTLINE;
+ }
}
else
return SILC_CONFIG_EINTERNAL;
SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
if (!strcmp(name, "timestamp")) {
- config->logging_timestamp = *(bool *)val;
+ config->logging_timestamp = *(SilcBool *)val;
}
else if (!strcmp(name, "quicklogs")) {
- config->logging_quick = *(bool *)val;
+ config->logging_quick = *(SilcBool *)val;
}
else if (!strcmp(name, "flushdelay")) {
int flushdelay = *(int *)val;
tmp->reconnect_interval_max = *(SilcUInt32 *)val;
}
else if (!strcmp(name, "reconnect_keep_trying")) {
- tmp->reconnect_keep_trying = *(bool *)val;
+ tmp->reconnect_keep_trying = *(SilcBool *)val;
}
else if (!strcmp(name, "key_exchange_rekey")) {
tmp->key_exchange_rekey = *(SilcUInt32 *)val;
}
else if (!strcmp(name, "key_exchange_pfs")) {
- tmp->key_exchange_pfs = *(bool *)val;
+ tmp->key_exchange_pfs = *(SilcBool *)val;
}
else if (!strcmp(name, "version_protocol")) {
CONFIG_IS_DOUBLE(tmp->version_protocol);
(*(char *)val ? strdup((char *) val) : NULL);
}
else if (!strcmp(name, "anonymous")) {
- tmp->anonymous = *(bool *)val;
+ tmp->anonymous = *(SilcBool *)val;
}
else if (!strcmp(name, "qos")) {
- tmp->qos = *(bool *)val;
+ tmp->qos = *(SilcBool *)val;
}
else if (!strcmp(name, "qos_rate_limit")) {
tmp->qos_rate_limit = *(SilcUInt32 *)val;
CONFIG_IS_DOUBLE(tmp->passphrase);
if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
(void *)&tmp->passphrase,
- &tmp->passphrase_len)) {
+ &tmp->passphrase_len, 0, NULL)) {
got_errno = SILC_CONFIG_EPRINTLINE;
goto got_err;
}
}
else if (!strcmp(name, "publickey")) {
if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
- (void *)&tmp->publickeys, NULL)) {
+ (void *)&config->server->repository, NULL,
+ SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
got_errno = SILC_CONFIG_EPRINTLINE;
goto got_err;
}
}
else if (!strcmp(name, "publickeydir")) {
- if (!my_parse_publickeydir((char *) val, (void *)&tmp->publickeys)) {
+ if (!my_parse_publickeydir((char *) val,
+ (void *)&config->server->repository,
+ SILC_SKR_USAGE_KEY_AGREEMENT)) {
got_errno = SILC_CONFIG_EPRINTLINE;
goto got_err;
}
CONFIG_IS_DOUBLE(tmp->passphrase);
if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
(void *)&tmp->passphrase,
- &tmp->passphrase_len)) {
+ &tmp->passphrase_len, 0, NULL)) {
got_errno = SILC_CONFIG_EPRINTLINE;
goto got_err;
}
}
else if (!strcmp(name, "publickey")) {
if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
- (void *)&tmp->publickeys, NULL)) {
+ (void *)&config->server->repository, NULL,
+ SILC_SKR_USAGE_SERVICE_AUTHORIZATION, tmp)) {
got_errno = SILC_CONFIG_EPRINTLINE;
goto got_err;
}
CONFIG_IS_DOUBLE(tmp->passphrase);
if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
(void *)&tmp->passphrase,
- &tmp->passphrase_len)) {
+ &tmp->passphrase_len, 0, NULL)) {
got_errno = SILC_CONFIG_EPRINTLINE;
goto got_err;
}
else if (!strcmp(name, "publickey")) {
CONFIG_IS_DOUBLE(tmp->publickeys);
if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
- (void *)&tmp->publickeys, NULL)) {
+ (void *)&config->server->repository, NULL,
+ SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
got_errno = SILC_CONFIG_EPRINTLINE;
goto got_err;
}
}
}
else if (!strcmp(name, "backup")) {
- tmp->backup_router = *(bool *)val;
+ tmp->backup_router = *(SilcBool *)val;
}
else
return SILC_CONFIG_EINTERNAL;
CONFIG_IS_DOUBLE(tmp->passphrase);
if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
(void *)&tmp->passphrase,
- &tmp->passphrase_len)) {
+ &tmp->passphrase_len, 0, NULL)) {
got_errno = SILC_CONFIG_EPRINTLINE;
goto got_err;
}
else if (!strcmp(name, "publickey")) {
CONFIG_IS_DOUBLE(tmp->publickeys);
if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
- (void *)&tmp->publickeys, NULL)) {
+ (void *)&config->server->repository, NULL,
+ SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
got_errno = SILC_CONFIG_EPRINTLINE;
goto got_err;
}
}
}
else if (!strcmp(name, "initiator")) {
- tmp->initiator = *(bool *)val;
+ tmp->initiator = *(SilcBool *)val;
}
else if (!strcmp(name, "backuphost")) {
CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
tmp->backup_replace_port = (SilcUInt16) port;
}
else if (!strcmp(name, "backuplocal")) {
- tmp->backup_local = *(bool *)val;
+ tmp->backup_local = *(SilcBool *)val;
}
else
return SILC_CONFIG_EINTERNAL;
/* Check for correctness of the configuration */
-static bool silc_server_config_check(SilcServerConfig config)
+static SilcBool silc_server_config_check(SilcServerConfig config)
{
- bool ret = TRUE;
+ SilcBool ret = TRUE;
SilcServerConfigServer *s;
SilcServerConfigRouter *r;
- bool b = FALSE;
+ SilcBool b = FALSE;
/* ServerConfig is mandatory */
if (!config->server_info) {
configuration object. The SilcServerConfig must be freed by calling
the silc_server_config_destroy function. */
-SilcServerConfig silc_server_config_alloc(const char *filename)
+SilcServerConfig silc_server_config_alloc(const char *filename,
+ SilcServer server)
{
SilcServerConfig config_new;
SilcConfigEntity ent;
config_new->refcount = 1;
config_new->logging_timestamp = TRUE;
config_new->param.reconnect_keep_trying = TRUE;
+ config_new->server = server;
/* obtain a config file object */
file = silc_config_open(filename);
/* Registers configured ciphers. These can then be allocated by the
server when needed. */
-bool silc_server_config_register_ciphers(SilcServer server)
+SilcBool silc_server_config_register_ciphers(SilcServer server)
{
SilcServerConfig config = server->config;
SilcServerConfigCipher *cipher = config->cipher;
silc_server_stop(server);
exit(1);
}
- } else {
-#ifdef SILC_SIM
- /* Load (try at least) the crypto SIM module */
- char buf[1023], *alg_name;
- SilcCipherObject cipher_obj;
- SilcSim sim;
-
- memset(&cipher_obj, 0, sizeof(cipher_obj));
- cipher_obj.name = cipher->name;
- cipher_obj.block_len = cipher->block_length;
- cipher_obj.key_len = cipher->key_length * 8;
-
- /* build the libname */
- snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
- cipher->module);
- sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
-
- alg_name = strdup(cipher->name);
- if (strchr(alg_name, '-'))
- *strchr(alg_name, '-') = '\0';
-
- if (silc_sim_load(sim)) {
- cipher_obj.set_key =
- silc_sim_getsym(sim, silc_sim_symname(alg_name,
- SILC_CIPHER_SIM_SET_KEY));
- SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
- cipher_obj.set_key_with_string =
- silc_sim_getsym(sim,
- silc_sim_symname(alg_name,
- SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
- SILC_LOG_DEBUG(("set_key_with_string=%p",
- cipher_obj.set_key_with_string));
- cipher_obj.encrypt =
- silc_sim_getsym(sim, silc_sim_symname(alg_name,
- SILC_CIPHER_SIM_ENCRYPT_CBC));
- SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
- cipher_obj.decrypt =
- silc_sim_getsym(sim, silc_sim_symname(alg_name,
- SILC_CIPHER_SIM_DECRYPT_CBC));
- SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
- cipher_obj.context_len =
- silc_sim_getsym(sim, silc_sim_symname(alg_name,
- SILC_CIPHER_SIM_CONTEXT_LEN));
- SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
-
- /* Put the SIM to the list of all SIM's in server */
- silc_dlist_add(server->sim, sim);
-
- silc_free(alg_name);
- } else {
- SILC_LOG_ERROR(("Error configuring ciphers"));
- silc_sim_free(sim);
- silc_server_stop(server);
- exit(1);
- }
-
- /* Register the cipher */
- silc_cipher_register(&cipher_obj);
-#else
- SILC_LOG_ERROR(("Dynamic module support not compiled, "
- "can't load modules!"));
- silc_server_stop(server);
- exit(1);
-#endif
}
cipher = cipher->next;
} /* while */
/* Registers configured hash functions. These can then be allocated by the
server when needed. */
-bool silc_server_config_register_hashfuncs(SilcServer server)
+SilcBool silc_server_config_register_hashfuncs(SilcServer server)
{
SilcServerConfig config = server->config;
SilcServerConfigHash *hash = config->hash;
silc_server_stop(server);
exit(1);
}
- } else {
-#ifdef SILC_SIM
- /* Load (try at least) the hash SIM module */
- SilcHashObject hash_obj;
- SilcSim sim;
-
- memset(&hash_obj, 0, sizeof(hash_obj));
- hash_obj.name = hash->name;
- hash_obj.block_len = hash->block_length;
- hash_obj.hash_len = hash->digest_length;
-
- sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
-
- if ((silc_sim_load(sim))) {
- hash_obj.init =
- silc_sim_getsym(sim, silc_sim_symname(hash->name,
- SILC_HASH_SIM_INIT));
- SILC_LOG_DEBUG(("init=%p", hash_obj.init));
- hash_obj.update =
- silc_sim_getsym(sim, silc_sim_symname(hash->name,
- SILC_HASH_SIM_UPDATE));
- SILC_LOG_DEBUG(("update=%p", hash_obj.update));
- hash_obj.final =
- silc_sim_getsym(sim, silc_sim_symname(hash->name,
- SILC_HASH_SIM_FINAL));
- SILC_LOG_DEBUG(("final=%p", hash_obj.final));
- hash_obj.context_len =
- silc_sim_getsym(sim, silc_sim_symname(hash->name,
- SILC_HASH_SIM_CONTEXT_LEN));
- SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
-
- /* Put the SIM to the table of all SIM's in server */
- silc_dlist_add(server->sim, sim);
- } else {
- SILC_LOG_ERROR(("Error configuring hash functions"));
- silc_sim_free(sim);
- silc_server_stop(server);
- exit(1);
- }
-
- /* Register the hash function */
- silc_hash_register(&hash_obj);
-#else
- SILC_LOG_ERROR(("Dynamic module support not compiled, "
- "can't load modules!"));
- silc_server_stop(server);
- exit(1);
-#endif
}
hash = hash->next;
} /* while */
/* Registers configure HMACs. These can then be allocated by the server
when needed. */
-bool silc_server_config_register_hmacs(SilcServer server)
+SilcBool silc_server_config_register_hmacs(SilcServer server)
{
SilcServerConfig config = server->config;
SilcServerConfigHmac *hmac = config->hmac;
/* Registers configured PKCS's. */
-bool silc_server_config_register_pkcs(SilcServer server)
+SilcBool silc_server_config_register_pkcs(SilcServer server)
{
- SilcServerConfig config = server->config;
- SilcServerConfigPkcs *pkcs = config->pkcs;
-
- SILC_LOG_DEBUG(("Registering configured PKCS"));
-
- if (!pkcs)
- return FALSE;
-
- while (pkcs) {
- int i;
- for (i = 0; silc_default_pkcs[i].name; i++)
- if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
- silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
- break;
- }
- if (!silc_pkcs_is_supported(pkcs->name)) {
- SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
- silc_server_stop(server);
- exit(1);
- }
- pkcs = pkcs->next;
- } /* while */
-
return TRUE;
}
/* Returns TRUE if configuration for a router connection that we are
initiating exists. */
-bool silc_server_config_is_primary_route(SilcServer server)
+SilcBool silc_server_config_is_primary_route(SilcServer server)
{
SilcServerConfig config = server->config;
SilcServerConfigRouter *serv = NULL;
int i;
- bool found = FALSE;
+ SilcBool found = FALSE;
serv = config->routers;
for (i = 0; serv; i++) {
Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
char *host;
unsigned char *passphrase;
SilcUInt32 passphrase_len;
- SilcHashTable publickeys;
+ SilcBool publickeys;
SilcServerConfigConnParams *param;
struct SilcServerConfigClientStruct *next;
} SilcServerConfigClient;
char *nick;
unsigned char *passphrase;
SilcUInt32 passphrase_len;
- SilcHashTable publickeys;
+ SilcBool publickeys;
struct SilcServerConfigAdminStruct *next;
} SilcServerConfigAdmin;
char *host;
unsigned char *passphrase;
SilcUInt32 passphrase_len;
- SilcHashTable publickeys;
+ SilcBool publickeys;
SilcServerConfigConnParams *param;
- bool backup_router;
+ SilcBool backup_router;
struct SilcServerConfigServerStruct *next;
} SilcServerConfigServer;
char *host;
unsigned char *passphrase;
SilcUInt32 passphrase_len;
- SilcHashTable publickeys;
+ SilcBool publickeys;
SilcUInt16 port;
SilcServerConfigConnParams *param;
- bool initiator;
- bool backup_router;
+ SilcBool initiator;
+ SilcBool backup_router;
char *backup_replace_ip;
SilcUInt16 backup_replace_port;
- bool backup_local;
+ SilcBool backup_local;
struct SilcServerConfigRouterStruct *next;
} SilcServerConfigRouter;
/* define the SilcServerConfig object */
typedef struct {
+ SilcServer server;
void *tmp;
/* Reference count (when this reaches zero, config object is destroyed) */
/* The General section */
char *module_path;
- bool prefer_passphrase_auth;
- bool require_reverse_lookup;
+ SilcBool prefer_passphrase_auth;
+ SilcBool require_reverse_lookup;
SilcUInt32 channel_rekey_secs;
SilcUInt32 key_exchange_timeout;
SilcUInt32 conn_auth_timeout;
SilcServerConfigConnParams param;
- bool detach_disabled;
+ SilcBool detach_disabled;
SilcUInt32 detach_timeout;
- bool logging_timestamp;
- bool logging_quick;
+ SilcBool logging_timestamp;
+ SilcBool logging_quick;
long logging_flushdelay;
char *debug_string;
/* Prototypes */
/* Basic config operations */
-SilcServerConfig silc_server_config_alloc(const char *filename);
+SilcServerConfig silc_server_config_alloc(const char *filename,
+ SilcServer server);
void silc_server_config_destroy(SilcServerConfig config);
void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
void *ref_ptr);
void silc_server_config_unref(SilcServerConfigRef *ref);
/* Algorithm registering and reset functions */
-bool silc_server_config_register_ciphers(SilcServer server);
-bool silc_server_config_register_hashfuncs(SilcServer server);
-bool silc_server_config_register_hmacs(SilcServer server);
-bool silc_server_config_register_pkcs(SilcServer server);
+SilcBool silc_server_config_register_ciphers(SilcServer server);
+SilcBool silc_server_config_register_hashfuncs(SilcServer server);
+SilcBool silc_server_config_register_hmacs(SilcServer server);
+SilcBool silc_server_config_register_pkcs(SilcServer server);
void silc_server_config_setlogfiles(SilcServer server);
/* Run-time config access functions */
silc_server_config_find_router_conn(SilcServer server, char *host, int port);
SilcServerConfigRouter *
silc_server_config_find_backup_conn(SilcServer server, char *host);
-bool silc_server_config_is_primary_route(SilcServer server);
+SilcBool silc_server_config_is_primary_route(SilcServer server);
SilcServerConfigRouter *
silc_server_config_get_primary_router(SilcServer server);
SilcServerConfigRouter *
caller must recall the function with different nickname. If this returns
TRUE the new ID was created successfully. */
-bool silc_id_create_client_id(SilcServer server,
- SilcServerID *server_id, SilcRng rng,
- SilcHash md5hash,
- unsigned char *nickname, SilcUInt32 nick_len,
- SilcClientID **new_id)
+SilcBool silc_id_create_client_id(SilcServer server,
+ SilcServerID *server_id, SilcRng rng,
+ SilcHash md5hash,
+ unsigned char *nickname, SilcUInt32 nick_len,
+ SilcClientID **new_id)
{
unsigned char hash[16];
- bool finding = FALSE;
+ SilcBool finding = FALSE;
SILC_LOG_DEBUG(("Creating new Client ID"));
/* Creates Channel ID */
-bool silc_id_create_channel_id(SilcServer server,
- SilcServerID *router_id, SilcRng rng,
- SilcChannelID **new_id)
+SilcBool silc_id_create_channel_id(SilcServer server,
+ SilcServerID *router_id, SilcRng rng,
+ SilcChannelID **new_id)
{
- bool finding = TRUE;
+ SilcBool finding = TRUE;
SILC_LOG_DEBUG(("Creating new Channel ID"));
/* Checks whether the `server_id' is valid. It must be based to the
IP address provided in the `remote' socket connection. */
-bool silc_id_is_valid_server_id(SilcServer server,
- SilcServerID *server_id,
- SilcSocketConnection remote)
+SilcBool silc_id_is_valid_server_id(SilcServer server,
+ SilcServerID *server_id,
+ SilcPacketStream remote)
{
unsigned char ip[16];
+ const char *remote_ip;
+ SilcStream stream = silc_packet_stream_get_stream(remote);
- if (!silc_net_addr2bin(remote->ip, ip, sizeof(ip)))
+ silc_socket_stream_get_info(stream, NULL, NULL, &remote_ip, NULL);
+ if (!silc_net_addr2bin(remote_ip, ip, sizeof(ip)))
return FALSE;
- if (silc_net_is_ip4(remote->ip)) {
+ if (silc_net_is_ip4(remote_ip)) {
if (!memcmp(server_id->ip.data, ip, 4))
return TRUE;
} else {
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2005, 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Prototypes */
void silc_id_create_server_id(const char *ip, SilcUInt16 port, SilcRng rng,
SilcServerID **new_id);
-bool silc_id_create_client_id(SilcServer server,
- SilcServerID *server_id, SilcRng rng,
- SilcHash md5hash, unsigned char *nickname,
- SilcUInt32 nick_len,
- SilcClientID **new_id);
-bool silc_id_create_channel_id(SilcServer server,
- SilcServerID *router_id, SilcRng rng,
- SilcChannelID **new_id);
-bool silc_id_is_valid_server_id(SilcServer server,
- SilcServerID *server_id,
- SilcSocketConnection remote);
+SilcBool silc_id_create_client_id(SilcServer server,
+ SilcServerID *server_id, SilcRng rng,
+ SilcHash md5hash, unsigned char *nickname,
+ SilcUInt32 nick_len,
+ SilcClientID **new_id);
+SilcBool silc_id_create_channel_id(SilcServer server,
+ SilcServerID *router_id, SilcRng rng,
+ SilcChannelID **new_id);
+SilcBool silc_id_is_valid_server_id(SilcServer server,
+ SilcServerID *server_id,
+ SilcPacketStream remote);
#endif
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2002 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#define SERVERINCLUDES_H
/* Generic includes */
-#include "silcincludes.h"
+#include "silc.h"
/* Forward declaration for SILC Server object. The actual object is
defined in internal header file for server routines. I want to keep
typedef struct SilcServerStruct *SilcServer;
/* SILC Server includes */
-#include "idlist.h"
#include "serverconfig.h"
#include "server.h"
+#include "idlist.h"
#include "serverid.h"
#include "server_util.h"
#include "packet_send.h"
#include "packet_receive.h"
#include "route.h"
-#include "protocol.h"
#include "command.h"
#include "command_reply.h"
#include "server_query.h"
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
to stderr are changed to SILC_SERVER_LOG_ERROR() */
}
-static void signal_handler(int sig)
-{
- /* Mark the signal to be caller after this signal is over. */
- silc_schedule_signal_call(silcd->schedule, sig);
-}
-
SILC_TASK_CALLBACK(got_hup)
{
/* First, reset all log files (they might have been deleted) */
fprintf(fdd, " primary router : %s\n",
silcd->router->server_name ? silcd->router->server_name : "");
+#if 0
/* Dump socket connections */
{
int i;
- SilcSocketConnection s;
+ SilcPacketStream s;
fprintf(fdd, "\nDumping socket connections\n");
for (i = 0; i < silcd->config->param.connections_max; i++) {
(unsigned int)s->flags);
}
}
+#endif
/* Dump lists */
{
- SilcIDCacheList list = NULL;
+ SilcList list;
SilcIDCacheEntry id_cache = NULL;
SilcServerEntry server_entry;
SilcClientEntry client_entry;
fprintf(fdd, "\nDumping databases\n");
if (silc_idcache_get_all(silcd->local_list->servers, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
- fprintf(fdd, "\nServers in local-list:\n");
- c = 1;
- while (id_cache) {
+ c = 1;
+ fprintf(fdd, "\nServers in local-list:\n");
+ while ((id_cache = silc_list_get(list))) {
server_entry = (SilcServerEntry)id_cache->context;
fprintf(fdd, " %d: name %s id %s status 0x%x\n", c,
server_entry->server_name ? server_entry->server_name :
"N/A", server_entry->id ?
silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
server_entry->data.status);
- if (!silc_idcache_list_next(list, &id_cache))
- break;
c++;
- }
}
- silc_idcache_list_free(list);
}
if (silc_idcache_get_all(silcd->global_list->servers, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
fprintf(fdd, "\nServers in global-list:\n");
c = 1;
- while (id_cache) {
+ while ((id_cache = silc_list_get(list))) {
server_entry = (SilcServerEntry)id_cache->context;
fprintf(fdd, " %d: name %s id %s status 0x%x\n", c,
server_entry->server_name ? server_entry->server_name :
"N/A", server_entry->id ?
silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
server_entry->data.status);
- if (!silc_idcache_list_next(list, &id_cache))
- break;
c++;
- }
- }
- silc_idcache_list_free(list);
+ }
}
if (silc_idcache_get_all(silcd->local_list->clients, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
fprintf(fdd, "\nClients in local-list:\n");
c = 1;
- while (id_cache) {
+ while ((id_cache = silc_list_get(list))) {
client_entry = (SilcClientEntry)id_cache->context;
server_entry = client_entry->router;
fprintf(fdd, " %d: name %s id %s status 0x%x from %s\n", c,
client_entry->data.status, server_entry ?
server_entry->server_name ? server_entry->server_name :
"N/A" : "local");
- if (!silc_idcache_list_next(list, &id_cache))
- break;
c++;
}
- }
- silc_idcache_list_free(list);
}
if (silc_idcache_get_all(silcd->global_list->clients, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
fprintf(fdd, "\nClients in global-list:\n");
c = 1;
- while (id_cache) {
+ while ((id_cache = silc_list_get(list))) {
client_entry = (SilcClientEntry)id_cache->context;
server_entry = client_entry->router;
fprintf(fdd, " %d: name %s id %s status 0x%x from %s\n", c,
client_entry->data.status, server_entry ?
server_entry->server_name ? server_entry->server_name :
"N/A" : "local");
- if (!silc_idcache_list_next(list, &id_cache))
- break;
c++;
}
- }
- silc_idcache_list_free(list);
}
if (silc_idcache_get_all(silcd->local_list->channels, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
fprintf(fdd, "\nChannels in local-list:\n");
c = 1;
- while (id_cache) {
+ while ((id_cache = silc_list_get(list))) {
channel_entry = (SilcChannelEntry)id_cache->context;
fprintf(fdd, " %d: name %s id %s\n", c,
channel_entry->channel_name ? channel_entry->channel_name :
"N/A", channel_entry->id ?
silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
- if (!silc_idcache_list_next(list, &id_cache))
- break;
c++;
}
- }
- silc_idcache_list_free(list);
}
if (silc_idcache_get_all(silcd->global_list->channels, &list)) {
- if (silc_idcache_list_first(list, &id_cache)) {
fprintf(fdd, "\nChannels in global-list:\n");
c = 1;
- while (id_cache) {
+ while ((id_cache = silc_list_get(list))) {
channel_entry = (SilcChannelEntry)id_cache->context;
fprintf(fdd, " %d: name %s id %s\n", c,
channel_entry->channel_name ? channel_entry->channel_name :
"N/A", channel_entry->id ?
silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
- if (!silc_idcache_list_next(list, &id_cache))
- break;
c++;
}
- }
- silc_idcache_list_free(list);
}
}
#endif
int main(int argc, char **argv)
{
int ret, opt, option_index;
- bool foreground = FALSE;
- bool opt_create_keypair = FALSE;
+ SilcBool foreground = FALSE;
+ SilcBool opt_create_keypair = FALSE;
char *silcd_config_file = NULL;
struct sigaction sa;
printf("SILCd Secure Internet Live Conferencing daemon, "
"version %s (base: SILC Toolkit %s)\n",
silc_dist_version, silc_version);
- printf("(c) 1997 - 2005 Pekka Riikonen "
+ printf("(c) 1997 - 2007 Pekka Riikonen "
"<priikone@silcnet.org>\n");
exit(0);
break;
silc_hash_register_default();
silc_hmac_register_default();
silc_create_key_pair(opt_pkcs, opt_bits, pubfile, prvfile,
- opt_identifier, "", NULL, NULL, NULL, FALSE);
+ opt_identifier, "", NULL, NULL, FALSE);
exit(0);
}
silc_hmac_register_default();
/* Read configuration files */
- silcd->config = silc_server_config_alloc(silcd_config_file);
+ silcd->config = silc_server_config_alloc(silcd_config_file, silcd);
if (silcd->config == NULL)
goto fail;
silcd->config_file = silcd_config_file;
#endif /* SIGXCPU */
/* Handle specificly some other signals. */
- sa.sa_handler = signal_handler;
- sigaction(SIGHUP, &sa, NULL);
- sigaction(SIGTERM, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGUSR1, &sa, NULL);
- silc_schedule_signal_register(silcd->schedule, SIGHUP, got_hup, NULL);
- silc_schedule_signal_register(silcd->schedule, SIGTERM, stop_server, NULL);
- silc_schedule_signal_register(silcd->schedule, SIGINT, stop_server, NULL);
- silc_schedule_signal_register(silcd->schedule, SIGUSR1, dump_stats, NULL);
+ silc_schedule_task_add_signal(silcd->schedule, SIGHUP, got_hup, NULL);
+ silc_schedule_task_add_signal(silcd->schedule, SIGTERM, stop_server, NULL);
+ silc_schedule_task_add_signal(silcd->schedule, SIGINT, stop_server, NULL);
+ silc_schedule_task_add_signal(silcd->schedule, SIGUSR1, dump_stats, NULL);
if (!foreground) {
/* Before running the server, fork to background. */
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#define SILC_SERVER_PUBLIC_KEY_NAME "/silcd.pub"
#define SILC_SERVER_PRIVATE_KEY_NAME "/silcd.prv"
-#define SERVER_KEY_EXPIRATION_DAYS 180
-
#endif